Related
Like, if I write code that looks like the following:
const int & const_value = 10;
What advantage am I gaining over code that would instead look like this:
int value = 10;
or
const int const_value = 10;
Even for a more complicated example, like
const enterprise::complicated_class_which_takes_time_to_construct & obj = factory.create_instance();
Thanks to copy elision, both of the following code snippets shouldn't be significantly faster or less memory consuming.
enterprise::complicated_class_which_takes_time_to_construct obj = factory.create_instance();
or
const enterprise::complicated_class_which_takes_time_to_construct obj = factory.create_instance();
Is there something I'm missing that explains the use of this construct, or a hidden benefit I'm not accounting for?
Edit:
The answer provided by #nwp supplied the example of a factory method that looks like the following:
using cc = enterprise::complicated_class_which_takes_time_to_construct;
struct Factory{
const cc &create_instance(){
static const cc instance;
return instance;
}
} factory;
While this is a good example of why you'd need the exact const reference construct in general, it doesn't answer why it would be needed for dealing with temporaries, or why this particular construct would be better than just seating the temporary in a proper stack-allocated object, which the compiler should still be able to copy-elide in normal situations.
Imagine the factory is "clever" and does something like
using cc = enterprise::complicated_class_which_takes_time_to_construct;
struct Factory{
const cc &create_instance(){
static const cc instance;
return instance;
}
} factory;
and further assume cc is not copyable then the const & version works while the other 2 don't. This is fairly common for classes that implement a cache and keep a local map of objects and you get a reference to the object inside the map.
Edit:
It is possible a coding guideline would say Take return values from functions by const &, because that works universally with values and references.
cc foo();
cc &foo();
const cc &foo();
If you use const cc &var = foo(); it will work without an unnecessary copy in all the cases. Sometimes you get a temporary, sometimes you don't, but the code always does the right thing, freeing you to change the implementation and to not having to care about how the function you use returns its return-value. There is still the issue of having a const in there, so it is not the superior notation in all cases, but it is a viable design choice.
There's one "pathological" case that comes to mind: non-copyable and non-movable objects. Such an object cannot be stored by value, so holding it by a reference is your only chance:
#include <iostream>
struct Immovable
{
Immovable(int i) : i(i) {}
Immovable(const Immovable&) = delete;
Immovable(Immovable&&) = delete;
const int i;
};
Immovable factory()
{
return {42};
}
int main()
{
const Immovable &imm = factory();
std::cout << imm.i;
}
[Live example]
On a less contrived note, you dismissed the "heavy object" optimisation by citing copy elision. Note, however, that copy elision is optional. You can never guarantee that the compiler will do it. Storing the temporary in a const &, on the contrary, guarantees that no copying or moving will happen.
The rationale for the lifetime extension rule is known ¹(because Bjarne Stroustrup, the language creator, said so) to be to have uniform simple rules. In particular, the lifetime of a temporary used as actual argument in a function call, is extended to the end of the full-expression, covering the lifetime of any reference that it's bound to. And the rule for local reference to const, or local rvalue reference, makes that aspect of the behavior the same.
In C++03 one practical use case, as far as I know ²invented by Petru Marginean, was to create a local object of an unknown automatically deduced type, like this:
Base const& o = foo( arg1, arg2, arg3 );
This works when Base is an accessible base class of any possible foo result type, because the lifetime extension mechanism does not slice: it extends the lifetime of the full temporary object. When foo returns a T it's a complete T object that has its lifetime extended. The compiler knows T even though the programmer may not necessarily know T.
Of course, in C++11 and later one can instead, generally, use auto:
auto const o = foo( arg1, arg2, arg3 );
With return value optimization and/or moving this will be just as efficient as Marginean's trick, and it's more clear and simple.
However, when the type T is non-movable and non-copyable, then binding to a reference with lifetime extension of the temporary, appears to be the only way to hold on to it, which is a second use case.
Now, surprise?, the type T of the full temporary object needs not be derived from the statically known type. It's enough that compiler knows that you're holding a reference to a part of the temporary. Whether that part is a base class sub-object, or some other sub-object, doesn't matter, so you can do:
auto const& part = foo( arg1, arg2, arg3 ).a_part;
Which is a third use case, which is only about not introducing an otherwise never used name for the complete object, keeping the code simple.
Standardese about the hold-on-to-a-part (and thus the whole object) case:
C++15 §12.2/5 [class.temporary]
” The temporary to which the reference is
bound or the temporary that is the complete object of a subobject to which the reference is bound persists for the lifetime of the reference except …
The exceptions include that a temporary used as actual argument in a function call, persists till the end of the full-expression, i.e. a bit longer than any formal argument reference that it's bound to.
¹ In an exchange with me in the Usenet group comp.lang.c++.
² In the C++03 implementation of the ScopeGuard class, which was invented by Petru. In C++11 a ScopeGuard can be trivially implemented using std::function and auto in the client code's dceclaration.
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_;
};
I've upvoted comonad's answer, but with a caveat:
Whenever you want to explicitely
disallow move semantics, use a scoped_ptr const 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.
A auto_ptr is a pointer with copy and with move semantics and ownership (=auto-delete).
A unique_ptr is a auto_ptr without copy but with move semantics.
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.
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.
Edit: my bad, you DO need to write move(p) inside the initialiser. std::move treats whatever it's given as an rvalue reference, and in your case, even though your argument is an rvalue reference to something, passing it to something else (like p_'s constructor) will pass an lvalue reference, never an rvalue reference by default.
Per Karu's comment, also added necessary includes to made my code compilable.
For example:
#include <memory>
#include <cassert>
#include <vector>
using namespace std;
class A {};
class B {
public:
void takeOwnershipOf(unique_ptr<A>&& rhs) {
// We need to explicitly cast rhs to an rvalue when passing it to push_back
// (otherwise it would be passed as an lvalue by default, no matter what
// qualifier it has in the argument list). When we do that, the move
// constructor of unique_ptr will take ownership of the pointed-to value
// inside rhs, thus making rhs point to nothing.
owned_objects.push_back(std::move(rhs));
}
private:
vector<unique_ptr<A>> owned_objects;
};
int main() {
unique_ptr<B> b(new B());
// we don't need to use std::move here, because the argument is an rvalue,
// so it will automatically be transformed into an rvalue reference.
b->takeOwnershipOf( unique_ptr<A>(new A()) );
unique_ptr<A> a (new A());
// a points to something
assert(a);
// however, here a is an lvalue (it can be assigned to). Thus we must use
// std::move to convert a into an rvalue reference.
b->takeOwnershipOf( std::move(a) );
// whatever a pointed to has now been moved; a doesn't own it anymore, so
// a points to 0.
assert(!a);
return 0;
}
Also, in your original example, you should rewrite class A like this:
class A {
// takes ownership
A(unique_ptr&& p): p_(std::move(p)) {}
unique_ptr<P> p_;
};
Sometimes we like to take a large parameter by reference, and also to make the reference const if possible to advertize that it is an input parameter. But by making the reference const, the compiler then allows itself to convert data if it's of the wrong type. This means it's not as efficient, but more worrying is the fact that I think I am referring to the original data; perhaps I will take it's address, not realizing that I am, in effect, taking the address of a temporary.
The call to bar in this code fails. This is desirable, because the reference is not of the correct type. The call to bar_const is also of the wrong type, but it silently compiles. This is undesirable for me.
#include<vector>
using namespace std;
int vi;
void foo(int &) { }
void bar(long &) { }
void bar_const(const long &) { }
int main() {
foo(vi);
// bar(vi); // compiler error, as expected/desired
bar_const(vi);
}
What's the safest way to pass a lightweight, read-only reference? I'm tempted to create a new reference-like template.
(Obviously, int and long are very small types. But I have been caught out with larger structures which can be converted to each other. I don't want this to silently happen when I'm taking a const reference. Sometimes, marking the constructors as explicit helps, but that is not ideal)
Update: I imagine a system like the following: Imagine having two functions X byVal(); and X& byRef(); and the following block of code:
X x;
const_lvalue_ref<X> a = x; // I want this to compile
const_lvalue_ref<X> b = byVal(); // I want this to fail at compile time
const_lvalue_ref<X> c = byRef(); // I want this to compile
That example is based on local variables, but I want it to also work with parameters. I want to get some sort of error message if I'm accidentally passing a ref-to-temporary or a ref-to-a-copy when I think I'll passing something lightweight such as a ref-to-lvalue. This is just a 'coding standard' thing - if I actually want to allow passing a ref to a temporary, then I'll use a straightforward const X&. (I'm finding this piece on Boost's FOREACH to be quite useful.)
Well, if your "large parameter" is a class, the first thing to do is ensure that you mark any single parameter constructors explicit (apart from the copy constructor):
class BigType
{
public:
explicit BigType(int);
};
This applies to constructors which have default parameters which could potentially be called with a single argument, also.
Then it won't be automatically converted to since there are no implicit constructors for the compiler to use to do the conversion. You probably don't have any global conversion operators which make that type, but if you do, then
If that doesn't work for you, you could use some template magic, like:
template <typename T>
void func(const T &); // causes an undefined reference at link time.
template <>
void func(const BigType &v)
{
// use v.
}
If you can use C++11 (or parts thereof), this is easy:
void f(BigObject const& bo){
// ...
}
void f(BigObject&&) = delete; // or just undefined
Live example on Ideone.
This will work, because binding to an rvalue ref is preferred over binding to a reference-to-const for a temporary object.
You can also exploit the fact that only a single user-defined conversion is allowed in an implicit conversion sequence:
struct BigObjWrapper{
BigObjWrapper(BigObject const& o)
: object(o) {}
BigObject const& object;
};
void f(BigObjWrapper wrap){
BigObject const& bo = wrap.object;
// ...
}
Live example on Ideone.
This is pretty simple to solve: stop taking values by reference. If you want to ensure that a parameter is addressable, then make it an address:
void bar_const(const long *) { }
That way, the user must pass a pointer. And you can't get a pointer to a temporary (unless the user is being terribly malicious).
That being said, I think your thinking on this matter is... wrongheaded. It comes down to this point.
perhaps I will take it's address, not realizing that I am, in effect, taking the address of a temporary.
Taking the address of a const& that happens to be a temporary is actually fine. The problem is that you cannot store it long-term. Nor can you transfer ownership of it. After all, you got a const reference.
And that's part of the problem. If you take a const&, your interface is saying, "I'm allowed to use this object, but I do not own it, nor can I give ownership to someone else." Since you do not own the object, you cannot store it long-term. This is what const& means.
Taking a const* instead can be problematic. Why? Because you don't know where that pointer came from. Who owns this pointer? const& has a number of syntactic safeguards to prevent you from doing bad things (so long as you don't take its address). const* has nothing; you can copy that pointer to your heart's content. Your interface says nothing about whether you are allowed to own the object or transfer ownership to others.
This ambiguity is why C++11 has smart pointers like unique_ptr and shared_ptr. These pointers can describe real memory ownership relations.
If your function takes a unique_ptr by value, then you now own that object. If it takes a shared_ptr, then you now share ownership of that object. There are syntactic guarantees in place that ensure ownership (again, unless you take unpleasant steps).
In the event of your not using C++11, you should use Boost smart pointers to achieve similar effects.
You can't, and even if you could, it probably wouldn't help much.
Consider:
void another(long const& l)
{
bar_const(l);
}
Even if you could somehow prevent the binding to a temporary as input to
bar_const, functions like another could be called with the reference
bound to a temporary, and you'd end up in the same situation.
If you can't accept a temporary, you'll need to use a reference to a
non-const, or a pointer:
void bar_const(long const* l);
requires an lvalue to initialize it. Of course, a function like
void another(long const& l)
{
bar_const(&l);
}
will still cause problems. But if you globally adopt the convention to
use a pointer if object lifetime must extend beyond the end of the call,
then hopefully the author of another will think about why he's taking
the address, and avoid it.
I think your example with int and long is a bit of a red herring as in canonical C++ you will never pass builtin types by const reference anyway: You pass them by value or by non-const reference.
So let's assume instead that you have a large user defined class. In this case, if it's creating temporaries for you then that means you created implicit conversions for that class. All you have to do is mark all converting constructors (those that can be called with a single parameter) as explicit and the compiler will prevent those temporaries from being created automatically. For example:
class Foo
{
explicit Foo(int bar) { }
};
(Answering my own question thanks to this great answer on another question I asked. Thanks #hvd.)
In short, marking a function parameter as volatile means that it cannot be bound to an rvalue. (Can anybody nail down a standard quote for that? Temporaries can be bound to const&, but not to const volatile & apparently. This is what I get on g++-4.6.1. (Extra: see this extended comment stream for some gory details that are way over my head :-) ))
void foo( const volatile Input & input, Output & output) {
}
foo(input, output); // compiles. good
foo(get_input_as_value(), output); // compile failure, as desired.
But, you don't actually want the parameters to be volatile. So I've written a small wrapper to const_cast the volatile away. So the signature of foo becomes this instead:
void foo( const_lvalue<Input> input, Output & output) {
}
where the wrapper is:
template<typename T>
struct const_lvalue {
const T * t;
const_lvalue(const volatile T & t_) : t(const_cast<const T*>(&t_)) {}
const T* operator-> () const { return t; }
};
This can be created from an lvalue only
Any downsides? It might mean that I accidentally misuse an object that is truly volatile, but then again I've never used volatile before in my life. So this is the right solution for me, I think.
I hope to get in the habit of doing this with all suitable parameters by default.
Demo on ideone
is it possible to restrict class instances to be used only as rvalues (e.g. temporaries)?
for example, I have class Wrapper whose constructor takes A const& and saves this reference in its member. It's a dangerous because lifetime of Wrapper instance cannot be longer than lifetime of A instance, but it's fine if Wrapper is temporary.
I think that even wanting to do this is a sign of a really bad design.
However, you could make all constructors private and make a friend function that returns an rvalue. That should do the trick.
I don't think it would be safe:
const A &a = YourClass( tmp );
YourClass in this case is the class you're looking for which only allow temporary instances, tmp is the temporary value you pass to the constructor.
It's possible (ie: safe, defined behavior) to have a constant reference to a temporary (ie: a), but the temporary itself (such instance of YourClass) has got a reference to tmp which is no longer valid after that expression is evaluated.
Not exactly the answer you are looking for, but have you thought about weak pointers? (for example, boost::weak_ptr). In this case, the original A would be held in a shared_ptr and the Wrapper constructor accepts a weak_ptr. The neat thing with this approach is that, before each usage of the weak_ptr, you can attempt to lock() which will give you a shared_ptr - if that fails, you know that A is gone and Wrapper cannot function... But it's handled cleanly...
This might do the job unless your class has public data members.
Basically, the idea is not to restrict the construction of the wrapper but to make sure that instances can be used (just like you said) only as long as they are temporary values. One can achieve this by overloading all methods and deleting (or making them private) those that refer to const&.
Here's a simple example:
class Wrapper
{
public:
Wrapper() = default;
Wrapper(const std::string& name) : name(name) {}
void process() && { std::cout << "Greetings from " << name << std::endl; }
// Only temporary instances of this class are allowed!
void process() const & = delete;
private:
std::string name;
};
And some use cases:
Wrapper("John").process(); // intended use case
Wrapper j; // create whatever you want
j.process(); // error C2280: 'void Wrapper::process(void) const &': attempting to reference a deleted function
std::move(j).process(); // this is still possible
const Wrapper& t = Wrapper(); // bind the temporary to a const reference - not a problem because ...
t.process(); // error C2280: 'void Wrapper::process(void) const &': attempting to reference a deleted function
The obvious disadvantages are:
You have to overload every public member function.
The error message is delayed and not very informative.
A similar thing has been done in the standard. The make routines for std::reference_wrapper do not accept temporaries.
Note that they considered another subtlety: the overload uses const T&& instead of T&&. This can be important in our case as well. For example, if your wrapper is deliberately designed to be noncopyable and you use make routines such as
const Wrapper make_wrapper();
instead of
Wrapper make_wrapper();
In this case, you might want to replace
void process() &&;
by
void process() const &&;
I'd not bother enforcing this at compile time, as there are always going to be corner cases where this would be overly restrictive, limiting the usefulness of the class, but rather wrap tools like valgrind or Purify so I can spot places where invalidated references are used.
I believe in C++17 and later you can get approximately what you want by doing the following:
Delete the move constructor for your type (and don't define a copy constructor).
Always accept your type by value in APIs.
So, for example:
#include <type_traits>
#include <utility>
// A non-moveable, non-copyable type.
struct CantMove {
CantMove(CantMove&&) = delete;
CantMove(int) {} // Some other constructor
};
static_assert(!std::is_move_constructible_v<CantMove>);
static_assert(!std::is_copy_constructible_v<CantMove>);
// A function that accepts it by value.
bool AcceptByValue(CantMove input) { return true; }
// It's possible to call the value-accepting API when the input is a prvalue
// (which in previous versions of C++ would have been a temporary).
bool unused = AcceptByValue(CantMove(0));
// But it's not possible to call with a named value, even when casted to an
// rvalue reference. This doesn't compile.
CantMove cant_move(0);
bool unused_2 = AcceptByValue(std::move(cant_move));
It's possible to provide the value-accepting function with what we previously called a temporary because guaranteed copy elision says that there isn't even a temporary involved anymore—the only CantMove object created is the function parameter itself, so there is no move- or copy-construction involved. In contrast it's not possible to call with std::move(cant_move) because that would involve move-constructing the function parameter, and the type is not move-constructible.
Of course it's still possible to initialize a CantMove directly:
CantMove foo{0};
But if you own all of the APIs that accept a CantMove and make them all accept by value, then you can't actually do anything with foo afterward. This means it would be hard for a user to do this by mistake and not realize the problem.
Yes, you could.
You would make the constructor and regular copy-constructor/assign private but make the r-value move semantics (C++0x) public.
You would have a static or friend constructor to create the temporary.
In 2003 C++ you would also be able to use this to bind to a const reference.
Of course you'd have the issue that your const reference would probably become invalidated after the statement.
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_;
};
I've upvoted comonad's answer, but with a caveat:
Whenever you want to explicitely
disallow move semantics, use a scoped_ptr const 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.
A auto_ptr is a pointer with copy and with move semantics and ownership (=auto-delete).
A unique_ptr is a auto_ptr without copy but with move semantics.
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.
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.
Edit: my bad, you DO need to write move(p) inside the initialiser. std::move treats whatever it's given as an rvalue reference, and in your case, even though your argument is an rvalue reference to something, passing it to something else (like p_'s constructor) will pass an lvalue reference, never an rvalue reference by default.
Per Karu's comment, also added necessary includes to made my code compilable.
For example:
#include <memory>
#include <cassert>
#include <vector>
using namespace std;
class A {};
class B {
public:
void takeOwnershipOf(unique_ptr<A>&& rhs) {
// We need to explicitly cast rhs to an rvalue when passing it to push_back
// (otherwise it would be passed as an lvalue by default, no matter what
// qualifier it has in the argument list). When we do that, the move
// constructor of unique_ptr will take ownership of the pointed-to value
// inside rhs, thus making rhs point to nothing.
owned_objects.push_back(std::move(rhs));
}
private:
vector<unique_ptr<A>> owned_objects;
};
int main() {
unique_ptr<B> b(new B());
// we don't need to use std::move here, because the argument is an rvalue,
// so it will automatically be transformed into an rvalue reference.
b->takeOwnershipOf( unique_ptr<A>(new A()) );
unique_ptr<A> a (new A());
// a points to something
assert(a);
// however, here a is an lvalue (it can be assigned to). Thus we must use
// std::move to convert a into an rvalue reference.
b->takeOwnershipOf( std::move(a) );
// whatever a pointed to has now been moved; a doesn't own it anymore, so
// a points to 0.
assert(!a);
return 0;
}
Also, in your original example, you should rewrite class A like this:
class A {
// takes ownership
A(unique_ptr&& p): p_(std::move(p)) {}
unique_ptr<P> p_;
};