将对象的所有权从一个unique_ptr转移到C++ 11中的另一个unique_ptr?

Roy*_*Roy 31 c++ std move-semantics c++11

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

std::unique_ptr<int> p1(new int(42));
std::unique_ptr<int> p2 = std::move(p1); // Transfer ownership
Run Code Online (Sandbox Code Playgroud)

在将所有权转让给另一个所有权的情况下,这有什么用unique_ptr

Chr*_*rew 27

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

假设你有一些多态类型Animal:

struct Animal {
  virtual ~Animal() {}
  virtual void speak() = 0;
};
Run Code Online (Sandbox Code Playgroud)

具体的子类CatDog:

struct Cat : Animal {
  void speak() override { std::cout << "Meow!\n"; }
};

struct Dog : Animal {
  void speak() override { std::cout << "Woof!\n"; }
};
Run Code Online (Sandbox Code Playgroud)

而且你想要一个简单的工厂,根据所需的服从价值创造宠物.然后工厂必须返回一个指针.我们希望宠物工厂将创建的宠物的所有权转移给调用者,因此合理的返回类型是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>();
} 
Run Code Online (Sandbox Code Playgroud)

现在,假设我们想创建一个House拥有宠物的东西,那么我们可能想要将宠物传递给它的构造函数House.有一些争论(请参阅此博客文章的评论)关于如何最好地将a传递unique_ptr给构造函数,但它看起来像这样:

class House {
 private:
  std::unique_ptr<Animal> pet_;
 public:
  House(std::unique_ptr<Animal> pet) : pet_(std::move(pet)) {}
};
Run Code Online (Sandbox Code Playgroud)

我们已经将其传递给unique_ptr构造函数,然后将其"移动"到成员变量中.

调用代码可能类似于:

  auto pet = createPet(6.0);
  House house(std::move(pet));
Run Code Online (Sandbox Code Playgroud)

在构建之后House,pet变量将是nullptr因为我们将宠物的所有权转移到了House.

Live demo

  • @ jfritz42 r值引用本身就是l值,因此您仍然需要`std :: move`。[尝试一下](http://coliru.stacked-crooked.com/a/42b8222989a16651)。 (2认同)

use*_*710 7

例如,如果你调用一个函数,你可以moveunique_ptr在参数列表中,因此它可以是你的函数签名的一部分

foo ( std::unique_ptr<T>&& ptr )
Run Code Online (Sandbox Code Playgroud)

你可以打电话给 foo

foo( std::move(myPtr) );
Run Code Online (Sandbox Code Playgroud)

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

如果你想谈论你所指向的对象的所有权转让unique_ptr,你应该考虑swapstd::unique_ptr<T>它自己提供。

  • @ user1308004,虽然`std::move` 确实不会移动,它只是准备将其从其中移动,但在大多数情况下,这种区别并不重要,因此他们决定将其称为`std::move` . 我不明白使用 `std::move` 将所有权从一个 `unique_ptr` 转移到另一个的隐秘之处。这就是`unique_ptr` 有一个移动构造函数和移动赋值的原因。 (2认同)
  • 如果你想在函数调用中使用 `swap` 来转移所有权,你必须通过非常量引用传递,它根本不表达意图。通过 value 或 rvalue-ref 传递更好地表达意图。 (2认同)