2012-07-26 30 views
5

Tôi hiện đang nhận được bản thân mình vào c + + cho mã hóa cấp thấp hơn với opengl. Tôi đến từ một nền objc nặng vì vậy tôi có một số hiểu biết về quản lý bộ nhớ nhưng tôi dường như không thể có được như thế nào "tăng" thư viện quản lý các loại container như ptr_vector.Ptr_vector quản lý bộ nhớ như thế nào?

Tôi nghĩ rằng vấn đề của tôi liên quan đến thực tế là tôi không biết làm thế nào ptr_vector quản lý sự phá hủy của chính nó và các đối tượng của nó.

Xin hãy nhìn vào đoạn mã sau:

// Header file 
... 
ptr_vector<IObject3D> objects; 
... 

// Implementation file 
... 
void ApplicationEngine::init() 
{ 
    WavefrontObject3D *object = new WavefrontObject3D("Ninja.obj"); 
    objects.push_back(object); 
} 
... 

Vì vậy, đối với thực chất vấn: Tôi tạo ra một sự rò rỉ ở đây thông qua các "đối tượng" biến?

Tôi đang sử dụng để duy trì và giải phóng đối tượng của tôi bằng tay với các cuộc gọi rõ ràng trong objc: trước đây tôi đã phải alloc init các WavefrontObject3D object, thêm nó vào một mảng và sau đó release cùng đối tượng để tránh rò rỉ.

Nhưng khi tôi thêm delete object sau khi gọi số push_back, thì hàm gọi deconstructor của WavefrontObject3D object được gọi. Điều này cho tôi một gợi ý rằng ptr_vector không giữ lại biến số object. Giả định của tôi có đúng không?

bổ sung, nhưng có liên quan, câu hỏi: chúng ta hãy nói rằng tôi muốn để tiêu diệt các lớp chứa ApplicationEngine tôi không phải gọi một số loại deconstructor trên ptr_vector hoặc các yếu tố nó quản lý?

+0

'Nhưng khi tôi thêm đối tượng xóa sau cuộc gọi push_back, bộ giải mã của đối tượng WavefrontObject3D được gọi là' 'Vâng đó là những gì' xóa' được tạo cho. Nó gọi hàm hủy trên cá thể con trỏ trỏ tới. – Nobody

+1

Tôi nghĩ bạn nên đọc trên [RAII] (http://stackoverflow.com/q/395123/20984), đó là cách hầu hết quản lý bộ nhớ được thực hiện trong cái gọi là "hiện đại" C++. –

+0

Tài nguyên tuyệt vời @LucTouraille! Chính xác cách tôi muốn tiếp cận C++. – polyclick

Trả lời

5

Không, đây không tạo ra một sự rò rỉ. Tất cả các thùng chứa ptr_* sẽ xóa các đối tượng được lưu trữ trong đó khi vùng chứa nằm ngoài phạm vi.

Nếu bạn xóa đối tượng sau khi thêm đối tượng vào vùng chứa, bạn sẽ tạo undefined behavior vì vùng chứa sẽ cố gắng xóa lại nó.

Câu hỏi bổ sung: Không, nếu bạn lưu trữ ptr_vector theo giá trị, tuổi thọ của nó được quản lý bởi phạm vi của lớp xung quanh.

Hãy viết triển khai đơn giản ptr_vector. Nó không có sự hỗ trợ cho các trình vòng lặp gián tiếp và các thông số tùy chỉnh và nhiều thứ khác nhưng cho thấy các nguyên tắc được sử dụng.

template <typename T> 
class ptr_vector { 
public: 
    // assume control over it 
    void push_back(T* x) 
    { if(x) c_.push_back(x); else throw bad_pointer(); } 

    ~ptr_vector() { 
    // delete everything that is stored here 
    for(auto x : c_) delete x; 
    } 
private: 
    std::vector<T*> c_; 
}; 


// a user class 
struct user_class { 
    void addSomething() { x.push_back(new int(23)); } 
    ptr_vector<int> x; 
}; 

Nếu người dùng lớp đi ra khỏi phạm vi, destructor của ptr_vector sẽ được gọi và tất cả các bộ nhớ sẽ được khai hoang. Không có rò rỉ trong tầm nhìn.

+0

+1 để hiển thị các hoạt động bên trong của 'ptr_vector';) – polyclick

0

ptr_vector sẽ giải phóng tất cả các phần tử trong phần hủy, vì vậy bạn không phải làm gì hơn những gì bạn đã làm, tức là tạo các đối tượng, thêm chúng vào ptr_vector và để quản lý. Gọi delete một cách rõ ràng sẽ làm cho đối tượng bị phá hủy hai lần (một lần khi bạn yêu cầu và một lần nữa khi kết thúc ptr_vector). Nói cách khác, ptr_vector không trùng lặp đối tượng.

Khi kết thúc ApplicationEngine, nếu nó có một thể hiện của ptr_vector, thì hàm hủy của vectơ đó sẽ được gọi, do đó sẽ xóa các đối tượng được thêm vào.

2
void push_back(T* x); 

Yêu cầu: x = 0 Effects: Chèn con trỏ vào container và mất quyền sở hữu của nó Ném: bad_pointer nếu x == an toàn 0 Ngoại lệ: đảm bảo mạnh

template 
    < 
     class T, 
     class CloneAllocator = heap_clone_allocator, 
     class Allocator  = std::allocator<void*> 
    > 
    class ptr_vector : public ptr_sequence_adapter 
           < 
            T, 
            std::vector<void*,Allocator>, 
            CloneAllocator 
           > 

Vì vậy, bạn có thể chỉ định CloneAllocator riêng của mình và không xóa các phần tử được lưu trữ trong ptr_vector, nhưng heap_clone_allocator (mệnh giá mặc định cho CloneAllocator) sẽ xóa tất cả các phần tử được lưu trữ trong trình phá hủy.

http://www.boost.org/doc/libs/1_50_0/libs/ptr_container/doc/reference.html#class-heap-clone-allocator

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