Jump to content
  • Advertisement
Sign in to follow this  
Cornstalks

Polymorphic Smart Pointers

This topic is 3834 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

Is there a way that I can use polymorphism with smart pointers? More specifically, I have a std::stack of boost::shared_ptr<Base>. But when I tried stack.push(new Derived), the compiler gave me the following error:
no matching function for call to `std::stack<boost::shared_ptr<Base>, std::deque<boost::shared_ptr<Base>, std::allocator<boost::shared_ptr<Base> > > >::push(Derived*)' 
note C:\MinGW\include\c++\3.4.5\bits\stl_stack.h:191 candidates are: void std::stack<_Tp, _Sequence>::push(const typename _Sequence::value_type&) [with _Tp = boost::shared_ptr<Base>, _Sequence = std::deque<boost::shared_ptr<Base>, std::allocator<boost::shared_ptr<Base> > >]
Is there a way to do this?

Share this post


Link to post
Share on other sites
Advertisement
Just to add to the above post, it is potentially dangerous to use an unnamed temporary shared_ptr as it has the potential to cause a memory leak.

Something like this would be a better alternative.


boost::shared_ptr<Base> obj(new Derived(/*constructor arguments here*/));

stack.push(obj);

Share this post


Link to post
Share on other sites
Quote:
Original post by vtchill
Just to add to the above post, it is potentially dangerous to use an unnamed temporary shared_ptr as it has the potential to cause a memory leak.

Something like this would be a better alternative.

*** Source Snippet Removed ***


Actually it isn't a problem in that case. It would only be a problem if the function accepted multiple arguments.

reference

Share this post


Link to post
Share on other sites
Sweet, thanks to all! I'll try it out. I'm getting to the point where I'm using more and more polymorphic objects and I don't want to worry about memory leaks, so I figured I'd try to use some smart pointers for some extra safety.

[edit]

Works perfectly!

Share this post


Link to post
Share on other sites
To get back to the original post, a boost::shared_ptr<Base> can definitely be set to point to a Derived. I don't know why the compiler is giving you an error there but this really *should* work IMO.


P.S. Ah never mind ... I should learn to read posts before writing replies.

Share this post


Link to post
Share on other sites
Quote:
Original post by Red Ant
I don't know why the compiler is giving you an error there but this really *should* work IMO.


It doesn't because the shared_ptr constructor that takes a single pointer is explicit.

Share this post


Link to post
Share on other sites
Yeah sorry ... I hadn't read the post properly before replying. I see now that he was relying on an implicit conversion.

Share this post


Link to post
Share on other sites
Quote:
Original post by fpsgamer
Quote:
Original post by vtchill
Just to add to the above post, it is potentially dangerous to use an unnamed temporary shared_ptr as it has the potential to cause a memory leak.

Something like this would be a better alternative.

*** Source Snippet Removed ***


Actually it isn't a problem in that case. It would only be a problem if the function accepted multiple arguments.

reference


youch ... i never considered this. my code has a lot of this kind of thing, (the justification for the init() seperate from the constructor is for dealing with things that interact with shared_from_this())

class A
{
typedef shared_ptr< A> ptr;
static ptr create()
{
ptr p( new A);
p->init();
return p;
}
};


is it safe to use in this type of context.

vector< A::ptr>    va; 
va.push_back( A::create() );


i think its ok - its still a temporary being returned that is used as the const arg of the push_back method, but both the shared pointer and underlying object have been fully constructed and use_count() is always positive even if its only being held by a temporary. what about multiple argument functions . if one of the other arguments methods throws on the constructor - would that still be memory safe ?

Share this post


Link to post
Share on other sites
Quote:
Original post by chairthrower
i think its ok - its still a temporary being returned that is used as the const arg of the push_back method, but both the shared pointer and underlying object have been fully constructed and use_count() is always positive even if its only being held by a temporary. what about multiple argument functions . if one of the other arguments methods throws on the constructor - would that still be memory safe ?


The scenario you illustrated is safe.

The problem (as you've already noted) has to do with when you are dealing with multiple arguments.

Consider this:

void doStuff(boost::shared_ptr<Foo>(new Foo()), Bar() );

The order in which arguments are evaluated in C++ is undefined. If an exception is thrown at inopportune times you will get a resource leak. Consider this hypothetical argument evaluation order:


(1) exectute 'new Foo()'
(2) construct temporary Bar() object
(3) construct shared_ptr<Foo> from the value returned by 'new Foo()'

If (2) two throws an exception, stack unwinding will commence and we will loose a handle to the memory allocated in (1).

Thats why you should do this instead:

boost::shared_ptr<Foo>ptr(new Foo());
void doStuff(ptr, Bar() );


If stack unwinding begins as the result of a thrown exception, the shared_ptr will be destroyed and take appropriate care of the heap resource.

Further Reading.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!