简体   繁体   中英

boost shared_ptr: difference between operator= and reset?

Are there any differences between the two pieces of code below? Is any of them preferable to the other?

operator=

boost::shared_ptr<Blah> foo; // foo.ptr should be NULL
foo = boost::shared_ptr<Blah>(new Blah()); // Involves creation and copy of a shared_ptr?

reset

boost::shared_ptr<Blah> foo; // foo.ptr should be NULL
foo.reset(new Blah()); // foo.ptr should point now to a new Blah object

Note: I need to define the shared_ptr and then set it in a different line because I'm using it in a piece of code like:

boost::shared_ptr<Blah> foo;
try
{
  foo.reset...
}
foo...

operator= assigns a shared_ptr to a shared_ptr , while reset makes a shared_ptr take ownership of a pointer. So, basically there is no difference between the examples you have posted. That said, you should prefer neither of them and just use make_shared :

foo = boost::make_shared<Blah>();

Also, if possible, you can prevent having to declare a shared_ptr without initialization by wrapping the try-catch block in a separate function that simply returns a shared_ptr to the newly created object:

boost::shared_ptr<Blah> createBlah() {
    try {
        // do stuff
        return newBlah;
    }
    catch ...
}

operator= takes another shared_ptr as a parameter thus creating another copy (and upping the reference count) while reset() takes a pointer and optionally a deleter, thus in reality creating a new shared_ptr on top of the current one.

reset is equivalent to (and probably implemented as)

void reset(T p, D d)
{
   shared_ptr shared(p,d);
   swap( shared );
}

operator= is likely to be implemented as:

shared_ptr& operator=( shared_ptr const& other )
{
   shared_ptr shared(other);
   swap(other);
   return *this;
}

The two functions are similar in that they release control of what they are already containing, if any, and manage a different pointer instead.

foo.reset(p) is defined to be equivalent to shared_ptr(p).swap(foo) .

Assignment is logically equivalent to copy-and-swap, and possibly implemented that way. So foo = shared_ptr(p); is equivalent to foo.swap(shared_ptr(p)) . Possibly with an extra copy in there if the compiler is having a very bad day.

So in the examples you give, I don't think there's much to choose between them. There might be other cases where it matters. But reset does the same template-based capture of the static type of p that the template constructor does, so as far as getting the right deleter is concerned, you're covered.

The main use of assignment is when you want to copy a previously-existing shared_ptr , to share ownership of the same object. Of course it works fine when assigning from a temporary too, and if you look at the different reset overloads they mirror the different constructors. So I suspect you can achieve the same things either way.

Assignment operator create a new shared object from existing one, incrementing the reference count

CSharedObj& CSharedObj::operator=(CSharedObj& r) noexcept
{ 
     if(*this != r){
        //detach from the previous ownership
        if(0 == dec()) delete m_pControlObj;
        //attach to the new control object and increment the reference count
        r.inc();
        m_pControlObj = r.m_pControlObj;
    }
    return *this;
}

while the reset call doesn't create the new shared object, but rather a new ownership - attaching to the new underlying pointee ( via control object)

void CSharedObj::reset(Ptr pointee) noexcept
{
   //check if this is a last reference-detach from the previous ownership
   if(0==dec()) delete m_pControlObj;
   // create the ownership over the new pointee (refCnt = 1)
   m_pControlObj = new (std::nothrow) CControlObj(pointee);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM