Archived

This topic is now archived and is closed to further replies.

STL containers w/ pointers

This topic is 5673 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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]

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
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.


Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites
Guys. What you need is a reference counted pointer. Like the first AP said have a look at boost. www.boost.org

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites