Sign in to follow this  
Sean_Seanston

How does boost::shared_ptr/make_shared equality work?

Recommended Posts

I'm just trying to see if a shared_ptr is pointing to a certain object, but the equality isn't working as I expected.

 

It's basically like this:

Object boost::shared_pyr< Object > selObj = boost::make_shared< Object > (obj);
if( selObj == boost::make_shared< Object > (obj) )
{
}

I would have expected it to evaluate to true, but it doesn't.

 

Am I right in thinking that this means the == operator is not actually comparing the addresses being pointed to, but instead it's the make_shared objects, which are technically different instances in each case? That also seems somewhat strange to me if that's the case.

 

Either way, how should this be done? I want to see if they refer to the same Object, and definitely don't want to compare the Object's themselves for equality but make sure it only returns true if it's referring to the exact same instance.

 

(Not using std::shared_ptr because of my old compiler/computer, but I assume it probably works the same way as far as this is concerned anyway)

Share this post


Link to post
Share on other sites

The shared_ptr class behaves like a pointer, so testing for equality compares the pointer values. You create two shared pointer instances and they hold different instances of your Object class. It seems like this is the kind of comparison you want, but you just misunderstand that make_shared allocates a new copy and shares it.

Share this post


Link to post
Share on other sites


You create two shared pointer instances and they hold different instances of your Object class. It seems like this is the kind of comparison you want, but you just misunderstand that make_shared allocates a new copy and shares it.

 

Interesting... though actually, I just realized my example was a bit flawed; I never stated where "obj" was declared... in reality this code is within a function and it comes from an argument. Not that that matters really. (Not to mention the misspelling of ptr I just noticed... argh)

 

But I did not know that... hmmmm.

 

make_shared is conceptually the same as:

boost::shared_ptr<Object> selObj;
selObj.reset(new Object());

If that helps.

 

So I guess in practice that means... you use make_shared basically only everywhere that you want pass-by-value semantics?

 

That is certainly very useful to know, if that's the case.

 

Anyways, I tried replacing the shared_ptr with a simple pointer and it seems to work. Think the situation probably makes a simple pointer ok, so I may just leave it at that, or leave it at that once I'm finished making sure I understand how shared_ptr/make_shared works in this case...

Share this post


Link to post
Share on other sites

Ok, I definitely have been misunderstanding what make_shared is for... but am I right in thinking that in order to correctly use boost::shared_ptr to point to an existing object, you have to do the following:

boost::shared_ptr< Object > sP;
Object o;
sP = boost::shared_ptr< Object >( &o );

?

 

If so, I think I have it now.

Share this post


Link to post
Share on other sites

No, that won't work. Your object o has automatic storage and is managed automatically by the surrounding scope and will be destroyed when leaving the scope. You now also have a shared pointer that has assumed ownership of it and will also try to destroy it. Your code thus has conflicting ownership over the object o.

 

You have to allocate the object dynamically so that you can pass the full ownership of the resource to the shared pointer.

Share this post


Link to post
Share on other sites

Oh yes, that makes sense.

 

BUT on the other hand, would it also be reasonable to instead just use make_shared, because that would then be created its own dynamically allocated copy of o? If I'm getting this.

 

Also, after doing some more experimenting... is the following the correct/best/quickest way to compare the address of a shared_ptr's object and that of another object?:

boost::shared_ptr< Object > sP;
Object o;

if( sP.get() == &o )
{
}

Seems that way from what I can see.

Share this post


Link to post
Share on other sites

Oh yes, that makes sense.
 
BUT on the other hand, would it also be reasonable to instead just use make_shared, because that would then be created its own dynamically allocated copy of o? If I'm getting this.

That is that make_shared does: it allocates a new object, that you can then used to shared among other shared pointers.

 

Also, after doing some more experimenting... is the following the correct/best/quickest way to compare the address of a shared_ptr's object and that of another object?:

boost::shared_ptr< Object > sP;
Object o;

if( sP.get() == &o )
{
}
Seems that way from what I can see.

Unless you screw up ownership like in your last post, an object managed by a shared pointer and an object with automatic storage can never have the same address.

Share this post


Link to post
Share on other sites

So does that mean you can't really ever use boost::shared_ptr to refer to the actual instance of something like:

Object o;

?

 

Because then it's not managed by the shared_ptr, and that's the whole point of shared_ptr (because that's the only way it can ensure correct "garbage collection")?... I think I'm getting it now.

Share this post


Link to post
Share on other sites

Partly correct, given the actual wording you use. The different smart pointers are about managing ownership of the instance in various ways, but automatic objects are already owned and managed by the surrounding scope. The automatic ownership is not compatible with the shared ownership provided by the shared pointer.

 

You can, however, pass ownership to an existing object, but it has to be something that you can pass the ownership of. Dynamically allocated objects can have their ownership transferred, but automatic objects like you asked about cannot.

// allocat an object
Object *o = new Object;

...

// pass the object to the shared pointer and give it full ownership
shared_ptr<Object> s(o);
Edited by Brother Bob

Share this post


Link to post
Share on other sites

Hmmm... right... so is that because in that case, o already is a pointer and therefore allocated on the heap, whereas an object allocated on the stack has to be copied into the heap before using a shared_ptr can make any sense and by that time it's obviously referring to a different part of memory?

 

I hope I explained that right...

 

EDIT: Whereas raw pointers work because they just point to memory without asking any questions and don't care if they're pointing to stack memory, unlike shared_ptr which specifically avoids it?

Edited by Sean_Seanston

Share this post


Link to post
Share on other sites

Ok... I think now the only major uncertainty I have is with the "shared" nature of shared_ptr.

 

How does the syntax work for using multiple shared_ptr objects to refer to the same pointer? I think now it must be very different to how I might have imagined it.

 

If we declare a shared_ptr like this:

boost::shared_ptr< Object > sP1( new Object() );

then is it as simple as:

boost::shared_ptr< Object > sP2 = sP1;

?

Share this post


Link to post
Share on other sites


How does the syntax work for using multiple shared_ptr objects to refer to the same pointer? I think now it must be very different to how I might have imagined it.

 

How to create and use share_ptr instances

 

It's for std::shared_ptr, but it should be nearly identical for the boost version.

 

Lots of resources on the web for this.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this