boost shared_ptr: difference between operator= and reset?

前端 未结 4 1358
眼角桃花
眼角桃花 2021-02-13 22:55

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

operator=

boost::shared_ptr&         


        
相关标签:
4条回答
  • 2021-02-13 23:11

    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);
    }
    
    0 讨论(0)
  • 2021-02-13 23:12

    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 ...
    }
    
    0 讨论(0)
  • 2021-02-13 23:18

    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.

    0 讨论(0)
  • 2021-02-13 23:19

    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.

    0 讨论(0)
提交回复
热议问题