I have an object which holds a unique_ptr and as such can't be copy constructed without doing a deep copy (which I don't want).
I'd like to have std::any hold that object, but the only alternatives I've found is to either make std::any hold a pointer, which adds a useless indirection, or make my object have a unique ptr. The code bellow will hopefully illustrate my point:
//Compiled with clang++ -std=c++2a; clang version 5.0.0
#include <iostream>
#include <any>
#include <memory>
struct A {
std::unique_ptr<int> m = std::make_unique<int>(11);
A(A&& a): m(std::move(a.m)) {}
A() {}
};
struct B {
std::shared_ptr<int> m = std::make_shared<int>(11);
};
template<class T>
void use_any_ptr() {
std::any a{new T{}};
std::cout << *(std::any_cast<T*>(a)->m) << std::endl;
}
template<class T>
void use_any() {
std::any a{T{}};
std::cout << *(std::any_cast<T>(a).m) << std::endl;
}
int main() {
use_any_ptr<A>(); // Workaround using a pointer
use_any<B>(); // Workaround using shared pointer
use_any<A>(); // Breaks because A has no cc no matching constructor for initialization of 'std::any'
}
As far as I understand the construction of std::any seems to require copying of the object, however I'm unsure why the object couldn't simply be moved.
Is there a way to work around this ? That is, other than using a shared_ptr, which means I'm basically expressing the "wrong thing" for the sake of creating the any object or passing std::any a pointer (which is an unneeded level of indirection, since std::any holds a void pointer to the type to being with as far as I can tell).
Is there a different implementation of any that could use the move ctr at creation instead of the copy ctr ?
Or am I being silly and not understanding the "real" problem here ?
Or am I being silly and not understanding the "real" problem here ?
The problem is simple here: std::any has a copy constructor and thus it requires the object contained is copy constructible.
The way you can work around it is by defining a custom object that contains the pointer, that is copyable and that implements a proper logic for it (whatever proper means in your case, I can't see how you could copy an std::any and thus an object contained there that owns an std::unique_ptr, but maybe you can get away with it somehow in your case).
Otherwise rethink your design and try to get rid of the need of an std::any. It hasn't much uses indeed and probably you can get the same with a bit of template machinery or an std::variant or whatever
Related
This blog post describes a technique for creating a container of heterogeneous pointers. The basic trick is to create a trivial base class (i.e. no explicit function declarations, no data members, nothing) and a templated derived class for storing std::function<> objects with arbitrary signatures, then make the container hold unique_ptrs to objects of the base class. The code is also available on GitHub.
I don't think this code can be made robust; std::function<> can be created from a lambda, which might include a capture, which might include a by-value copy of a nontrivial object whose destructor must be called. When the Func_t type is deleted by unique_ptr upon removal from the map, only its (trivial) destructor will be called, so the std::function<> objects never get properly deleted.
I've replaced the use-case code from the example on GitHub with a "non-trivial type" that is then captured by value inside a lambda and added to the container. In the code below, the parts copied from the example are noted in comments; everything else is mine. There's probably a simpler demonstration of the problem, but I'm struggling a bit to even get a valid compile out of this thing.
#include <map>
#include <memory>
#include <functional>
#include <typeindex>
#include <iostream>
// COPIED FROM https://plus.google.com/+WisolCh/posts/eDZMGb7PN6T
namespace {
// The base type that is stored in the collection.
struct Func_t {};
// The map that stores the callbacks.
using callbacks_t = std::map<std::type_index, std::unique_ptr<Func_t>>;
callbacks_t callbacks;
// The derived type that represents a callback.
template<typename ...A>
struct Cb_t : public Func_t {
using cb = std::function<void(A...)>;
cb callback;
Cb_t(cb p_callback) : callback(p_callback) {}
};
// Wrapper function to call the callback stored at the given index with the
// passed argument.
template<typename ...A>
void call(std::type_index index, A&& ... args)
{
using func_t = Cb_t<A...>;
using cb_t = std::function<void(A...)>;
const Func_t& base = *callbacks[index];
const cb_t& fun = static_cast<const func_t&>(base).callback;
fun(std::forward<A>(args)...);
}
} // end anonymous namespace
// END COPIED CODE
class NontrivialType
{
public:
NontrivialType(void)
{
std::cout << "NontrivialType{void}" << std::endl;
}
NontrivialType(const NontrivialType&)
{
std::cout << "NontrivialType{const NontrivialType&}" << std::endl;
}
NontrivialType(NontrivialType&&)
{
std::cout << "NontrivialType{NontrivialType&&}" << std::endl;
}
~NontrivialType(void)
{
std::cout << "Calling the destructor for a NontrivialType!" << std::endl;
}
void printSomething(void) const
{
std::cout << "Calling NontrivialType::printSomething()!" << std::endl;
}
};
// COPIED WITH MODIFICATIONS
int main()
{
// Define our functions.
using func1 = Cb_t<>;
NontrivialType nt;
std::unique_ptr<func1> f1 = std::make_unique<func1>(
[nt](void)
{
nt.printSomething();
}
);
// Add to the map.
std::type_index index1(typeid(f1));
callbacks.insert(callbacks_t::value_type(index1, std::move(f1)));
// Call the callbacks.
call(index1);
return 0;
}
This produces the following output (using G++ 5.1 with no optimization):
NontrivialType{void}
NontrivialType{const NontrivialType&}
NontrivialType{NontrivialType&&}
NontrivialType{NontrivialType&&}
NontrivialType{const NontrivialType&}
Calling the destructor for a NontrivialType!
Calling the destructor for a NontrivialType!
Calling the destructor for a NontrivialType!
Calling NontrivialType::printSomething()!
Calling the destructor for a NontrivialType!
I count five constructor calls and four destructor calls. I think that indicates that my analysis is correct--the container cannot properly destroy the instance it owns.
Is this approach salvageable? When I add a virtual =default destructor to Func_t, I see a matching number of ctor/dtor calls:
NontrivialType{void}
NontrivialType{const NontrivialType&}
NontrivialType{NontrivialType&&}
NontrivialType{NontrivialType&&}
NontrivialType{const NontrivialType&}
Calling the destructor for a NontrivialType!
Calling the destructor for a NontrivialType!
Calling the destructor for a NontrivialType!
Calling NontrivialType::printSomething()!
Calling the destructor for a NontrivialType!
Calling the destructor for a NontrivialType!
... so I think this change might be sufficient. Is it?
(Note: the correctness--or lack thereof--of this approach is independent of whether the idea of a container of heterogeneous functions is a good idea. In a few very specific cases, there may be some merit, for instance, when designing an interpreter; e.g., a Python class may be thought of as just such a container of heterogeneous functions plus a container of heterogeneous data types. But in general, my decision to ask this question does not indicate that I think this is likely to be a good idea in very many cases.)
This is basically someone trying to implement type erasure and getting it horribly wrong.
Yes, you need a virtual destructor. The dynamic type of the thing being deleted is obviously not Func_t, so it's plainly UB if the destructor isn't virtual.
The whole design is completely broken, anyway.
The point of type erasure is that you have a bunch of different types that share a common characteristic (e.g. "can be called with an int and get a double back"), and you want to make them into a single type that has that characteristic (e.g., std::function<double(int)>). By its nature, type erasure is a one-way street: once you have erased the type, you can't get it back without knowing what it is.
What does erasing something down to an empty class mean? Nothing, other than "it's a thing". It's a std::add_pointer_t<std::common_type_t<std::enable_if_t<true>, std::void_t<int>>> (more commonly known as void*), obfuscated in template clothing.
There are plenty of other problems with the design. Because the type was erased into nothingness, it had to recover the original type in order to do anything useful with it. But you can't recover the original type without knowing what it is, so it ends up using the type of arguments passed to Call to infer the type of the thing stored in the map. That is ridiculously error-prone, because A..., which represents the types and value categories of the arguments passed to Call, is highly unlikely to match exactly the parameter types of std::function's template argument. For instance, if you have a std::function<void(int)> stored in there, and you tried to call it with a int x = 0; Call(/* ... */ , x);, it's undefined behavior. Go figure.
To make it worse, any mismatch is hidden behind a static_cast that causes undefined behavior, making it harder to find and fix. There's also the curious design that requires the user to pass a type_index, when you "know" what the type is anyway, but it's just a sideshow when compared to all the other problems with this code.
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_;
};
In the code below, I made p const because it will never point to any other int during Foo's lifetime. This doesn't compile, as the unique_ptr's copy constructor is called, which is obviously deleted. Are there any solutions besides making p non-const? Thanks.
#include <memory>
using namespace std;
class Foo
{
public:
//x is a large struct in reality
Foo(const int* const x) : p(x) {};
Foo(Foo&& foo) : p(std::move(foo.p)) {};
private:
const unique_ptr<int> p;
};
The semantics of your move constructor are contradictory.
You have declared a const std::unique_ptr which will (uniquely) own the value it is initialised with.
But you've declared a move constructor that should move that value into another object at construction.
So what do you think should happen to the std::unique_ptr in the 'temporary' being move constructed from?
If you want it to be release()ed you've violated its constness.
If you want it to retain its value you've violated the constraint of std::unique which requires no more than one such object to own any given object.
Checkmate.
This problem reveals a subtle limitation of the C++ language. It requires move semantics to leave the copied to and from as valid objects.
There are several quite reasonable proposals for 'destructive move' which would in truth better reflect what most uses of move are doing - take a value to here from there 'invalidating' what was there.
Google them. I haven't made a literature survey so don't want to recommend one.
Your alternatives here are to remove const or cast it way.
I strongly recommend removing it. You can make sure the semantics of your class ensure the appropriate const-ness with no impact and no 'ugly suspect' const_cast.
#include <iostream>
#include <memory>
class Foo
{
public:
Foo(const int x) : p(new int(x)) {};
Foo(Foo&& foo) :
p(std::move(foo.p)) {
};
int get(void)const{
return *(this->p);
}
private:
std::unique_ptr<int> p;
};
Foo getMove(){
return Foo(88);
}
int main(){
Foo bar(getMove());
std::cout<<bar.get()<<std::endl;
return EXIT_SUCCESS;
}
To understand why your code does not compile, reflect how you have declared Foo class and how move semantics is generally implemented.
Declaring a const unique_ptr<T> p, you mean that p itself will be never modified, but you could still modify the pointed-to object because of T is not const.
But move works on an opposite assumption. This feature uses the idea that is allowed stealing resources from objects and leave them in a empty state (if an empty state make sense). If can be useful, think move as a sort of 'destructive' copy for the moved object.
Writing std::move(foo.p), basically you steal the resource pointed by foo.p and leave it in a safe state, that means assign foo.p to NULL. But foo.p was declared as const, so the operation is not permitted.
Please consider that in your case you don't need to declare p as a const unique_ptr<int>. Simply declare it as unique_ptr<int> and make sure that member functions are declared as const and non-member functions take it as
const unique_ptr<int> p& parameter. In this way you are sure that p will never change along the object lifetime (except in case of move operation).
It is because unique_ptr has only the move-constructor, which means the initialization argument to p cannot be const, while p is const. I think what you wanted was to declare
unique_ptr p;
instead of
const unique_ptr p;
class Foo {
public:
// x is a large struct in reality
Foo(const int* const x) : p(x) {};
Foo(Foo&& foo) : p(std::move(foo.p)) {};
private:
const unique_ptr<int> p;
};
Concept of using std::unique_ptr is representing a sole ownership of an object. What you're trying to achieve is having a Foo class own an object (which is expressed by std::unique_ptr) and making it movable (your move constructor) which makes a contradiction. I would stick with std::unique_ptr or make it shared using std::shared_ptr.
You might want to read this:
Smart Pointers: Or who owns you baby?
If you want to prevent transfer of ownership, you can use a const std::unique_ptr<T>. This is not very useful.
If you want to prevent modifying the object it holds, you can use a std::unique_ptr<const T>.
With the following code, "hello2" is not displayed as the temporary string created on Line 3 dies before Line 4 is executed. Using a #define as on Line 1 avoids this issue, but is there a way to avoid this issue without using #define? (C++11 code is okay)
#include <iostream>
#include <string>
class C
{
public:
C(const std::string& p_s) : s(p_s) {}
const std::string& s;
};
int main()
{
#define x1 C(std::string("hello1")) // Line 1
std::cout << x1.s << std::endl; // Line 2
const C& x2 = C(std::string("hello2")); // Line 3
std::cout << x2.s << std::endl; // Line 4
}
Clarification:
Note that I believe Boost uBLAS stores references, this is why I don't want to store a copy. If you suggest that I store by value, please explain why Boost uBLAS is wrong and storing by value will not affect performance.
Expression templates that do store by reference typically do so for performance, but with the caveat they only be used as temporaries
Taken from the documentation of Boost.Proto (which can be used to create expression templates):
Note An astute reader will notice that the object y defined above will be left holding a dangling reference to a temporary int. In the sorts of high-performance applications Proto addresses, it is typical to build and evaluate an expression tree before any temporary objects go out of scope, so this dangling reference situation often doesn't arise, but it is certainly something to be aware of. Proto provides utilities for deep-copying expression trees so they can be passed around as value types without concern for dangling references.
In your initial example this means that you should do:
std::cout << C(std::string("hello2")).s << std::endl;
That way the C temporary never outlives the std::string temporary. Alternatively you could make s a non reference member as others pointed out.
Since you mention C++11, in the future I expect expression trees to store by value, using move semantics to avoid expensive copying and wrappers like std::reference_wrapper to still give the option of storing by reference. This would play nicely with auto.
A possible C++11 version of your code:
class C
{
public:
explicit
C(std::string const& s_): s { s_ } {}
explicit
C(std::string&& s_): s { std::move(s_) } {}
std::string const&
get() const& // notice lvalue *this
{ return s; }
std::string
get() && // notice rvalue *this
{ return std::move(s); }
private:
std::string s; // not const to enable moving
};
This would mean that code like C("hello").get() would only allocate memory once, but still play nice with
std::string clvalue("hello");
auto c = C(clvalue);
std::cout << c.get() << '\n'; // no problem here
but is there a way to avoid this issue without using #define?
Yes.
Define your class as: (don't store the reference)
class C
{
public:
C(const std::string & p_s) : s(p_s) {}
const std::string s; //store the copy!
};
Store the copy!
Demo : http://www.ideone.com/GpSa2
The problem with your code is that std::string("hello2") creates a temporary, and it remains alive as long as you're in the constructor of C, and after that the temporary is destroyed but your object x2.s stills points to it (the dead object).
After your edit:
Storing by reference is dangerous and error prone sometimes. You should do it only when you are 100% sure that the variable reference will never go out of scope until its death.
C++ string is very optimized. Until you change a string value, all will refer to the same string only. To test it, you can overload operator new (size_t) and put a debug statement. For multiple copies of same string, you will see that the memory allocation will happen only once.
You class definition should not be storing by reference, but by value as,
class C {
const std::string s; // s is NOT a reference now
};
If this question is meant for general sense (not specific to string) then the best way is to use dynamic allocation.
class C {
MyClass *p;
C() : p (new MyClass()) {} // just an example, can be allocated from outside also
~C() { delete p; }
};
Without looking at BLAS, expression templates typically make heavy use of temporary objects of types you aren't supposed to even know exists. If Boost is storing references like this within theirs, then they would suffer the same problem you see here. But as long as those temporary objects remain temporary, and the user doesnt store them for later, everything is fine because the temporaries they reference remain alive for as long as the temporary objects do. The trick is you perform a deep copy when the intermediate object is turned into the final object that the user stores. You've skipped this last step here.
In short, it's a dangerous move, which is perfectly safe as long as the user of your library doesn't do anything foolish. I wouldn't recommend making use of it unless you have a clear need, and you're well aware of the consequences. And even then, there might be a better alternative, I've never worked with expression templates in any serious capacity.
As an aside, since you tagged this C++0x, auto x = a + b; seems like it would be one of those "foolish" things users of your code can do to make your optimization dangerous.
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_;
};