Edit: мой плохой, вам действительно нужно написать move(p)
внутри инициализатора. std::move
обрабатывает все, что указано в качестве ссылки на rvalue, и в вашем случае, даже если ваш аргумент является ссылкой на rvalue на что-то, передача его чему-то другому (например, конструктору p_
) передаст ссылку на lvalue, никогда Ссылка на значение по умолчанию.
Согласно комментарию Кару, также добавлены необходимые включения, чтобы сделать мой код компилируемым.
Например:
#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;
}
Кроме того, в исходном примере вы должны переписать класс A следующим образом:
класс А {
// вступает во владение
A (unique_ptr
&& p): p_ (std :: move (p)) {}
unique_ptr<P> p_;
* * 1016};