在C++11
中,我们可以使用unique_ptr
将对象的所有权转移到另一个std::move()
。所有权转移后,放弃所有权的智能指针变为null
,get()
返回nullptr.
std::unique_ptr<int> p1(new int(42));
std::unique_ptr<int> p2 = std::move(p1); // Transfer ownership
在将所有权转移到另一个unique_ptr
时,这会有什么用处?
答案 0 :(得分:25)
以下情况涉及将所有权从一个unique_ptr
转移到另一个:从函数返回,并作为参数传递给类似构造函数的函数。
假设你有一些多态类型Animal
:
struct Animal {
virtual ~Animal() {}
virtual void speak() = 0;
};
具体的子类Cat
和Dog
:
struct Cat : Animal {
void speak() override { std::cout << "Meow!\n"; }
};
struct Dog : Animal {
void speak() override { std::cout << "Woof!\n"; }
};
你想要一个简单的工厂,根据所需的服从价值创造宠物。然后工厂必须返回一个指针。我们希望宠物工厂将创建的宠物的所有权转移给调用者,因此合理的返回类型为std::unique_ptr<Animal>
:
std::unique_ptr<Animal> createPet(double obedience) {
if (obedience > 5.0)
return std::make_unique<Dog>();
return std::make_unique<Cat>();
}
现在,假设我们要创建一个拥有宠物的House
,那么我们可能希望将宠物传递给House
的构造函数。关于如何最好地将unique_ptr
传递给构造函数存在一些争论(see comments on this blog post),但它看起来像这样:
class House {
private:
std::unique_ptr<Animal> pet_;
public:
House(std::unique_ptr<Animal> pet) : pet_(std::move(pet)) {}
};
我们已将unique_ptr
传递给构造函数,然后将其“移动”到成员变量。
调用代码可能类似于:
auto pet = createPet(6.0);
House house(std::move(pet));
构建House
后,pet
变量将为nullptr
,因为我们已将宠物的所有权转移到House
。
答案 1 :(得分:4)
例如,如果您调用某个函数,则可以在参数列表中move
unique_ptr
,这样它就可以成为函数签名的一部分
foo ( std::unique_ptr<T>&& ptr )
你可以用
打电话给foofoo( std::move(myPtr) );
请注意,std::move
是无条件转换,unique_ptr
是具有状态的对象,该状态的一部分是unique_ptr
正在管理的指针,{{1你正在投射整个对象,你并没有真正改变所有权,使用std::move
时std::unique_ptr
没有什么特别之处,因为std::move
并不真正关心任何事情具体来说,正如我所说它是一个无条件的强制转换而std::move
只是被转换,整个对象是类型为unique_ptr
的实例。
如果您想谈论unique_ptr<T>
指向的对象的所有权转移,您应该考虑std::unique_ptr<T>
本身提供的unique_ptr
。