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开发者_如何学Go=
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);
}
精彩评论