Question

I just stumbled on the boost::shared_ptr documentation, which goes:

Sometimes it is necessary to obtain a shared_ptr given a raw pointer
to an object that is already managed by another shared_ptr instance.
Example:

void f(X * p) 
{
    shared_ptr<X> px(???);
}

Inside f, we'd like to create a shared_ptr to *p.

In the general case, this problem has no solution.

Why? Is it not allowed to do something like:

shared_ptr<X> px(p);

Am I missing something?

Was it helpful?

Solution

If you have a shared_ptr managing a pointer and then create another shared_ptr managing the same pointer (NOT copying the original shared_ptr), you end up with two managers for the same resource. When one of the two reach a reference count of 0, it will delete the object and the other shared_ptr will point to deleted memory with all that follows.

OTHER TIPS

If you would do this:

main() {
  Object *obj = new Object();
  func(obj)
}

void func( Object *obj ) {
  shared_ptr objPtr(obj); // take ownership.
  objPtr->fun();
  // Passed object "obj" is destroyed here.
}

At the end of the function func the object pointer would get destroyed, and with the pointer the object itself. This wouldn't be a desirable behaviour.

Actually, you can do that, but you must know that the pointed object will be deleted when exiting the function...

I tried with boost:

void f(X * p)
{
    boost::shared_ptr<X> px(p);
    // do smething
}

void main()
{
    X* ptr = new X();
    f( ptr );
    // ptr is not valid anymore because the object were deleted
}

Jean

You could do it, but it could lead to undefined behavior, since there is no way to tell the second shared pointer that the reference count (the number of shared pointers pointing at the same object) increased. Then things like this could happen:

void f()
{
    boost::shared_ptr<int> firstSmart(new int(23)); // firstSmart is the only 
                                                    // manager of the int
    int *raw = firstSmart.get();
    boost::shared_ptr<int> secondSmart(raw);        // secondSmart also manages
                                                    // the same int as firstSmart
                                                    // but secondSmart does not 
                                                    // know about firstSmart
                                                    // and vice versa
}

when f exits secondSmart gets destroyed, destroying the shared int. Then firstSmart gets destroyed and attempts to destroy the already destroyed int thus leading to undefined behaviour.

Its not possible to do this.

Shared pointers work using reference counting. When you assign a resource (raw pointer) to a shared pointer a reference count object is created with count =1. When another shared pointer is created for the same resource the reference count object (which is shared between both the shared pointers) is updated to value count =2. If one shared pointer is deleted the count in the shared reference object is decremented and when it reached 0 the resource is destroyed.

For the above mechanism to work the first shared pointer should be created using something like shared_ptr px(p) and all subsequent ones using px (not 'p'). This way all the shared pointers created will know that they are holding same resource and share the same reference count object.

If you created another shared pointer using shared_ptr px(p) then you end up with two shared pointer not related to each other - i.e there reference count objects are not same. They both assume that they are holding distinct resource and each of them have distinct (different) reference count object with count =1. (You don’t want this).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top