STL containers w/ pointers

Started by
8 comments, last by FrigidHelix 21 years, 10 months ago
I want to use STL containers to hold pointers. The catch is, these pointers need to be deleted once the container item is disposed of. For example, if I have a vector called v, i should be able to call: v.push_back( new SomeClass(...) ); and be able to rely on the fact that the memory get deallocated. I figured one potential way would be to use "safe pointers" which encapsulate the pointer into a templatized class. Is "safe pointers" the right lingo? because I tried searching the forums for it, but didn't find anything useful. That being said, is there a "standard" class out there that I can use for that effect, or must I write my own? I tried writing my own class, but I ran into some ... complications. Here is how i create a vector of pointers to some class X, and add a pointer to the list: vector< SafePointer< X > > v; v.push_back( new X(2) ); The problem with this, is that in order to push_back() an item, a temporary SafePointer is created. The temporary SafePointer is then copied using the copy constructor, and then destroyed. This is problematic indeed, because as soon as that temporary SafePointer variable goes out of scope, it deletes the memory that I just created, thereby making the element in vector invalid. Even more frustrating, is that fact that temporary variables are "const". As such, I can't tweak the copy constructor to flag a conditional delete boolean, so the old SafePointer knows not to delete itself. So, what I am doing right now in my SafePointer class is to allocate the memory AGAIN during the copy constructor. While this works for simple cases, it isnt suitable for my application. I don't want to have to construct the pointer memory over again. So, in short, how do i get this code to work right: v.push_back( new SomeClass(...) ); ? Here is my condensed code for SafePointer:
    template <typename T>
class SafePointer
{
	T* p;
public:
	SafePointer(T* inP) : p(inP) { }
	SafePointer( const SafePointer<T>& sp){ p = new T(*sp.p); }
	~SafePointer() { if(p) delete p; }
	T* operator->() { return p; }
};    
[edited by - FrigidHelix on June 5, 2002 4:05:13 AM]
Advertisement
Two things:

1. Take a look at the Boost implemetation of shared_ptr. If you are going to use any "smart pointer" implementation in an STL container this is what you should use. auto_ptr should be avoided like the plague. Effective STL item 8 explains why.. speaking of which:

2. Pickup a copy of Effective STL. It talks about a lot of these problems and how to deal with them. There are many other suggestions in there as well - very good reference IMHO.


I''m having this same problem, anybody got any solutions?
-Pac "The thing I like about friends in my classes is that they can't access my private members directly." "When listening to some one tell about their problem (whether it's code or not), don't listen to what went right or wrong, but what they assumed....."
Actually, I just found a workaround to the problem. If you keyword you deletion flag as "mutable", you can change it, even if "this" is const. Using this keyword (instead of doing an icky typecast on "this"), you can modify variables in the copy-constructor argument, hence being able to set its deletion flag to off. Here is the modified SafePointer code:


    template <typename T>class SafePointer{	T* p;	mutable bool fDelete;public:	SafePointer(T* inP) : p(inP), fDelete(true) { }	SafePointer( const SafePointer<T>& sp) : p(sp.p), fDelete(sp.fDelete)	{		// sp is const, so we wouldn't normally be able to modify it		// however, fDelete is keyworded "mutable"		sp.fDelete = false;	}	~SafePointer()	{		if(p && fDelete)			delete p;	}	T* operator->() { return p; }};    


Now, u can safely do stuff like:
vector< SafePointer< X > > v;
v.push_back( new X(2) );

without having to worry about the creation of the temporary variable.

EDIT: WTH? it keeps truncating my '<' and '>'. adding spaces between them to negate the effect.

[edited by - FrigidHelix on June 5, 2002 1:34:02 PM]
Guys. What you need is a reference counted pointer. Like the first AP said have a look at boost. www.boost.org
I found some good reading on the topic:

http://ootips.org/yonat/4dev/smart-pointers.html
-Pac "The thing I like about friends in my classes is that they can't access my private members directly." "When listening to some one tell about their problem (whether it's code or not), don't listen to what went right or wrong, but what they assumed....."
damn..

the boost library is big
daerid@gmail.com
It can only be downloaded as one unit ... but it is meant to be usable as only the modules you care about ... so you can include and use the shared_ptr stuff without the unrelated modules.

And yes, a reference counted pointer is the most common safe pointer type that is compatible with the STL ... auto_ptr''s and other pointers that transfer ownership are not appropriate.
i checked it out of CVS :\
daerid@gmail.com
Unless you really want smart-pointers inside the container, you can explicitly delete the contents of the container in it''s parent object''s dtor. It''s not quite as elegant as a self-maintaining smart-pointer container, but it is a bit less hassle.


  struct DeleteObj{template<typename T>void operator()(T* p){delete p;}};//..~MyObj(){std::for_each(this->cont.begin(), this->cont.end(), DeleteObj() );}  


"smart pointers" is the lingo; safe is ambiguous, because making the smart pointer safe for one thing often makes it dangerous for something else
- The trade-off between price and quality does not exist in Japan. Rather, the idea that high quality brings on cost reduction is widely accepted.-- Tajima & Matsubara

This topic is closed to new replies.

Advertisement