2010-07-16 22 views
26

Tôi đang làm việc trên một đoạn mã có nhiều điểm lỗi có thể khiến nó thoát khỏi chức năng sớm. Các thư viện tôi đang tương tác với yêu cầu các mảng kiểu C được truyền cho các hàm. Vì vậy, thay vì gọi xóa trên các mảng tại tất cả các điểm xuất cảnh, tôi đang làm điều này:Bạn có thể sử dụng shared_ptr cho RAII của mảng kiểu C không?

void SomeFunction(int arrayLength) 
{ 
    shared_ptr<char> raiiArray(new char[arrayLength]); 
    pArray = raiiArray.get(); 

    if(SomeFunctionThatRequiresCArray(pArray) == FAILED) { return; } 

    //etc. 
} 

Tôi muốn sử dụng unique_ptr, nhưng trình biên dịch hiện tại của tôi không hỗ trợ nó và tham chiếu đếm trên đầu không thực sự quan trọng trong trường hợp này.

Tôi chỉ tự hỏi liệu có ai có bất kỳ suy nghĩ nào về thực tiễn này khi giao tiếp với mã cũ không.

CẬP NHẬT Tôi hoàn toàn quên mất shared_ptr gọi delete thay vì delete []. Tôi chỉ thấy không có rò rỉ bộ nhớ và quyết định đi với nó. Thậm chí không nghĩ đến việc sử dụng một véc-tơ. Kể từ khi tôi đã được delving vào mới (đối với tôi) C + + gần đây tôi nghĩ rằng tôi đã có một trường hợp của "Nếu công cụ duy nhất bạn có là một cái búa, tất cả mọi thứ trông giống như một móng tay." hội chứng. Cảm ơn vì bạn đã phản hồi.

UPDATE2 Tôi figured tôi sẽ thay đổi câu hỏi và cung cấp một câu trả lời để làm cho nó có giá trị hơn một chút cho ai đó làm cho cùng một sai lầm tôi đã làm. Mặc dù có những lựa chọn thay thế như scoped_array, shared_arrayvector, bạn có thể sử dụng một shared_ptr để quản lý phạm vi của một mảng (nhưng sau này tôi không có ý tưởng tại sao tôi muốn):

template <typename T> 
    class ArrayDeleter 
    { 
    public: 
     void operator() (T* d) const 
     { 
      delete [] d; 
     } 
    }; 

void SomeFunction(int arrayLength) 
    { 
     shared_ptr<char> raiiArray(new char[arrayLength], ArrayDeleter<char>()); 
     pArray = raiiArray.get(); 

     if(SomeFunctionThatRequiresCArray(pArray) == FAILED) { return; } 

     //etc. 
    } 
+1

nitpicking: [[shared_ptr]] không hoạt động chính xác trên con trỏ mảng động. sử dụng [[scoped_array]] hoặc [[shared_array]]. – rwong

Trả lời

27

Không sử dụng shared_ptr hoặc scoped_ptr để giữ con trỏ tới mảng được phân bổ động. shared_ptr và scoped_ptr sử dụng delete ptr; để làm sạch khi con trỏ không còn được tham chiếu/đi ra khỏi phạm vi, mà gọi hành vi không xác định trên mảng được phân bổ động. Thay vào đó, sử dụng shared_array hoặc scoped_array, sử dụng chính xác delete[] ptr; khi hủy.

Để trả lời câu hỏi của bạn, nếu bạn không chuyển con trỏ thông minh xung quanh, hãy sử dụng scoped_array vì nó có ít chi phí hơn shared_array.

Cách khác, sử dụng std::vector làm bộ nhớ mảng (vectơ đã đảm bảo cấp phát bộ nhớ liền kề).

+7

Theo mặc định, shared_ptr và scoped_ptr sử dụng xóa ptr, nhưng bạn có thể cung cấp chức năng deleter của riêng bạn hoặc functor. – George

5

boost::scoped_ptr cho việc này.

+7

scoped_array trong trường hợp này –

+0

Có, chắc chắn, chúng đều ở đó. Cảm ơn. –

15

Sử dụng boost::scoped_array hoặc thậm chí tốt hơn std::vector nếu bạn đang xử lý mảng.

3

này

shared_ptr<char*> raiiArray(new char[arrayLength]); 

không phải là một thói quen tốt, nhưng gây ra hành vi không xác định, như bạn phân bổ với nhà điều hành new[], nhưng shared_ptr sử dụng operator delete để giải phóng bộ nhớ. Điều phù hợp để sử dụng là boost::shared_array hoặc thêm một deleter tùy chỉnh.

7

Tôi đặc biệt khuyên bạn chỉ nên sử dụng một số std::vector. Các phần tử trong vectors được cấp phát trên heap và sẽ bị xóa khi số vector vượt quá phạm vi, bất cứ nơi nào bạn thoát khỏi hàm.

Để chuyển mã vector tới mã cũ yêu cầu mảng kiểu C, chỉ cần vượt qua &vectorName[0]. Các yếu tố được đảm bảo tiếp giáp trong bộ nhớ.

+0

Đảm bảo rằng vectơ không rỗng trước khi sử dụng '& vectorName [0]' hoặc '& vectorName.front()', vì nó không xác định hoặc xác nhận hành vi cho một số triển khai. – AshleysBrain

6

Một số nhận xét cho C++ 11 người sử dụng:

Đối shared_ptr, có trong C++ 11 một deleter mặc định với nhiều loại mảng quy định tại <memory> và phù hợp tiêu chuẩn (WRT dự thảo cuối cùng) để nó có thể được sử dụng mà không deleters ưa thích bổ sung cho những trường hợp như:

std::shared_ptr<char> raiiArray(new char[arrayLength], std::default_delete<char[]>()); 

unique_ptr trong C++ 11 có một chuyên môn hóa một phần để đối phó với new[]delete[]. Nhưng nó không có một hành vi chia sẻ, thật không may. Phải là một lý do chính đáng không có chuyên môn như vậy cho shared_ptr nhưng tôi đã không tìm kiếm nó, nếu bạn biết điều đó, xin vui lòng chia sẻ nó.

+1

Theo [câu trả lời SO] (http://stackoverflow.com/a/8947700/1094609), lý do cuối cùng không có chuyên môn mảng cho 'shared_ptr' là" [T] ở đây chưa bao giờ là một đề xuất bằng văn bản thực tế ở phía trước của LWG để làm điều này. " –

Các vấn đề liên quan