在C++11中,将对象的所有权从一个unique_ptr转移到另一个unique _ptr

Transferring the ownership of object from one unique_ptr to another unique_ptr in C++11?

本文关键字:unique ptr 一个 另一个 转移 C++11 对象 所有权      更新时间:2023-10-16

C++11中,我们可以使用std::move()将对象的所有权转移到另一个unique_ptr。所有权转移后,放弃所有权的智能指针变为nullget()返回nullptr.

std::unique_ptr<int> p1(new int(42));
std::unique_ptr<int> p2 = std::move(p1); // Transfer ownership

当它将所有权转移到另一个unique_ptr时,在哪些情况下这将是有用的?

以下情况涉及将所有权从一个unique_ptr转移到另一个:从函数返回,并作为参数传递给类似构造函数的函数。

假设你有一些多态型Animal:

struct Animal {
  virtual ~Animal() {}
  virtual void speak() = 0;
};

具有具体的子类CatDog:

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传递给构造函数,有一些争论(请参阅本文的评论),但它看起来像这样:

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

现场演示

例如,如果您调用一个函数,您可以在参数列表中move您的unique_ptr,这样它就可以成为函数签名的一部分

foo ( std::unique_ptr<T>&& ptr )

你可以用调用foo

foo( std::move(myPtr) );

请注意,std::move是一个无条件强制转换,unique_ptr是一个有状态的对象,该状态的一部分是unique_ptr正在管理的指针,使用std::move时,您正在强制转换整个对象,您并没有真正更改任何关于所有权的内容,在使用std::move时,std::unique_ptr没有什么特殊之处,因为std::move并不真正关心任何特定的东西,正如我所说的,它是一个无条件的强制转换,unique_ptr只是被强制转换,作为unique_ptr<T>类型实例的整个对象都被强制转换。

如果您想讨论unique_ptr所指向对象的所有权转移,您应该考虑std::unique_ptr<T>本身提供的swap