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_;
};
A
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
#include
#include
using namespace std;
class A {};
class B {
public:
void takeOwnershipOf(unique_ptr&& 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> owned_objects;
};
int main() {
unique_ptr 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(new A()) );
unique_ptr 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_;
};