web-dev-qa-db-ja.com

C ++ 11でunique_ptrから別のunique_ptrにオブジェクトの所有権を転送しますか?

_C++11_では、std::move()を使用して、オブジェクトの所有権を別の_unique_ptr_に転送できます。所有権の譲渡後、所有権を譲渡したスマートポインターはnullになり、get()は_nullptr._を返します。

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

所有権を別の_unique_ptr_に転送しているため、これが役立つ状況は何ですか?

31
Roy

次の状況では、ある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をコンストラクターに渡す最善の方法については、いくつかの議論があります( このブログ投稿のコメントを参照 )が、次のようになります。

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になります。

Live demo

27
Chris Drew

たとえば、関数を呼び出す場合は、パラメータリストでunique_ptrmoveできるため、関数シグネチャの一部になります。

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

fooを呼び出すことができます

foo( std::move(myPtr) );

std::moveは無条件キャストであり、unique_ptrは状態を持つオブジェクトであり、その状態の一部はunique_ptrが管理しているポインターであり、std::moveを使用するとオブジェクト全体をキャストすることになります。 std::unique_ptrは無条件のキャストであり、std::moveが単にキャストされると言ったので、std::moveは実際には特定のものを何も気にしないので、unique_ptrの使用中にunique_ptr<T>に特有のことはありません。

unique_ptrが指すオブジェクトの所有権の移転について話したい場合は、 std::unique_ptr<T> 自体が提供するswapを考慮する必要があります。

4
user2485710