How does boost::shared_ptr/make_shared equality work?

Started by
12 comments, last by phil_t 9 years ago

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)

Advertisement

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.

make_shared is conceptually the same as:


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

If that helps.

SlimDX | Ventspace Blog | Twitter | Diverse teams make better games. I am currently hiring capable C++ engine developers in Baltimore, MD.


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...

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.

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.

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.

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.

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.

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);

This topic is closed to new replies.

Advertisement