I used to write code like this:
class P {};
class Q: public P {};
class A {
// takes ownership
A(P* p): p_(p) {}
scoped_ptr<P> p_;
};
A a(new Q);
With C++0x, should I rewrite class A as:
class A {
// takes ownership
A(unique_ptr<P>&& p): p_(p) {}
unique_ptr<P> p_;
};
A scoped_ptr is a auto_ptr without copy and without move semantics.
auto_ptrs are allways a bad choice – that is obvious.
Whenever you want to explicitely have move semantics, use a unique_ptr.
Whenever you want to explicitely disallow move semantics, use a scoped_ptr.
All pointers allow swap semantics, like p.swap(q)
. To disallow those, use any const …_ptr.
There are situations, where you want to use a scoped_ptr pointing to one of several interchangeable objects: Because of the absence of move semantics, it is quite safe (in respect to obvious bugs) that it will not accidentally point to null because of an unintended move. Worth to mention: scoped_ptrs can still be swapped efficiently. To make it movable and/or copyable – but still with these swap semantics – you might want to consider using a shared_ptr pointing to a scoped_ptr pointing to an exchangeable (via scoped_ptr::swap) object.
See stackoverflow:smart-pointers-boost-explained for further details.
I've upvoted comonad's answer, but with a caveat:
Whenever you want to explicitely disallow move semantics, use a
scoped_ptrconst unique_ptr.
I have not come across any use cases where a const std::unique_ptr
is inferior to a boost::scoped_ptr
. However I'm open to education on the subject.
Edit:
Here is a use case of boost::scoped_ptr
that I think should fail, but does not. It does fail for std::unique_ptr
:
#include <iostream>
#ifdef USE_UNIQUEPTR
#include <memory>
typedef std::unique_ptr<int> P;
#else // USE_UNIQUEPTR
#include <boost/scoped_ptr.hpp>
typedef boost::scoped_ptr<int> P;
#endif // USE_UNIQUEPTR
int main()
{
P p1(new int(1));
{
// new scope
#ifdef USE_UNIQUEPTR
const P p2(new int(2));
#else // USE_UNIQUEPTR
P p2(new int(2));
#endif // USE_UNIQUEPTR
swap(p1, p2); // should fail!
}
std::cout << *p1 << '\n';
}
If the promise of boost::scoped_ptr
is that its resource will not escape the current scope, then it is not as good at holding that promise as a const std::unique_ptr
. If we want to compare const boost::scoped_ptr to const::std::unique_ptr, I have to ask: for what purpose? They seem the same to me, except that a const std::unique_ptr allows customized construction and destruction.
IMO it is better to use unique_ptr
as it provides an additional feature: move semantics. i.e. you can write a move constructor, etc for your class, unlike scoped_ptr
. Also, unique_ptr
doesn't have an overhead associated with it as it is the case with scoped_ptr
, so it is a superior facility. A decision of a rewrite is up to you of course, in case you don't need move semantics then there is no point of the rewrite. Don't forget that unique_ptr
is from the standard library, so it must be provided with any compliant implementation of C++0x(when it becomes reality of course :)!
I have to disagree with AraK on one being superior. There is no such thing as a superior choice between the two as it often depends on usage. That's like saying a SmartCar is superior to a pick-up truck for all uses because it's lighter and faster. In reality, sometimes you need a truck and sometimes you don't. Your choice of pointer should be based on what you need.
The nice thing about scoped_ptr is it adds a level of safety. By using scoped_ptr you are delcaring that the memory created will exist only for that scope and no more, thus you get compile-time protection against attempting to move it or transfer it.
So, if you want to create somethign but limit it's scope, used scoped_ptr. If you want to create something and have ownership be movable, use unique_ptr. If you want to create something and share that pointer and cleanup when all referencers are gone, use shared_ptr.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With