STL vector frustrations

Started by
13 comments, last by Kranar 19 years, 10 months ago
copy constructor and assignment operator and destructor

Rule Of Three

If you have one, you probably need them all cos you have resources that need careful management.
Advertisement
The example I posted was really just meant as a simplified example to prove that the destructors are being called since snk_kid said they weren't, so I wanted to verify and confirm that they infact are. My real problem really has nothing to do with that simplified example.

My actual class does indeed have a copy constructor, assignment operator, and its own destructor. To go into further details about my problem, basically it's a smart pointer class I'm working with. When you declare the smart pointer to equal a real pointer, the smart pointer gets "ownership" over that pointer, meaning it will be responsible for deleting it when the smart pointer is destroyed, no other smart pointer will have the right to delete the contents. This ownership is nontransferrable and is only assigned when a smart pointer is given the value of an actual pointer.

So the copy constructor does not transfer ownership over to the smart pointer to copy into. So when I have a vector of smart pointers, and push onto the vector a new smart pointer, not only does the content of the smart point get deleted, but the ownership goes away.

The purpose of my smart pointer class is essentially to have multiple pointers pointing to the same object, but when the smart pointer with ownership finally deletes its contents, not only is it set to NULL, but all other smart pointers pointing to the same object are also set to NULL.

This way I can do something like this:

SmartPtr<int> x(new int(5));  // initial smart pointer, so it will have ownership over the int it allocatesSmartPtr<int> y;  // some other smart pointery = x;  // y will point to the contents of x, it will not have ownership over the contents though, so upon terminating, it will not delete the int that was allocatedx.release();  // x now deletes its contents, freeing memory and is set to NULL, additionally y is also set to NULLif(y != NULL) {  cout << *y << endl;} else {  cout << "Uh oh... y's contents have been deleted.\n" << endl;}


Now to fix my problem temporarily I set my copy constructor to transfer ownership. This really isn't what I hoped for, which is why I asked if there's a way to push onto a vector without having all the destructors called and that doesn't make use of copy constructors but simply does a binary copy. I guess I could make my own vector class because quite frankly, I think a simply binary copy would really speed things up. The final alternative will be to take ChaosEngine's advice, and use pointers to my smart pointers, which sounds rather funny but oh well.

[edited by - Kranar on June 10, 2004 3:40:47 AM]
Standard library containers have two requirements on the contained type: CopyConstructible and Assignable. In order to satisfy Assignable, given any two objects of the contained type T, t and u, then t = u must be valid and has the post-condition that t is equivalent to u. Since with your smart pointer class ownership is held by only the original object, logical equivalence fails. This makes your smart pointer unsuitible for use in any standard container.
Have you considered using the boost library before? They have a package that provides 6 different smart pointers including embedded reference count, some of them have been made to work with STL containers. Its very robust library.
The problem with your approach is that when x is released, y has no way of knowing that x was released. When you say you set the pointer to NULL, only x''s copy gets set to NULL, but when y tries to dereference the pointer, the memory it points to has already been freed so you get an access violation. You could potentially solve this by having the object that owns the pointer keep a list of all the other smart pointers that point to it but do not own it, but that would be tricky and quite wasteful in terms of memory and speed. The best solution that most people use is reference counting. Each object being pointed to keeps what''s called a reference count, which is the number of smart pointers that are currently pointing to it. When the reference count reaches zero, the object deletes itself (or has a global memory manager object delete it, or something similar). Whenever you call a smart pointer''s copy constructor or operator =, then you increment the object being pointed to''s reference count. Whenever you call operator = or when a smart pointer is destroyed (i.e. in the destructor), you decerement the old object''s reference count. Note that with this system, you cannot use pointers to primitive types (int, double, etc.) because they do not support reference counting themselves. You should make every object that a smart pointer can be pointed at a subclass of a reference-counting class. Reference counting also solves the problem of temporary copy objects, including when a vector needs to be resized and all of the elements need to be copied.

This topic is closed to new replies.

Advertisement