web-dev-qa-db-ja.com

std :: move()の後のunique_ptrはどうなりますか?

このコードは私がやりたいことです:

_Tony& Movie::addTony()
{
    Tony *newTony = new Tony;
    std::unique_ptr<Tony> tony(newTony);
    attachActor(std::move(tony));
    return *newTony;
}
_

代わりにこれを行うことができるかどうか疑問に思っています:

_Tony& Movie::addTony()
{
    std::unique_ptr<Tony> tony(new Tony);
    attachActor(std::move(tony));
    return *tony.get();
}
_

しかし、*tony.get()は同じポインターまたはnullになりますか?検証できることは知っていますが、標準的なことは何ですか?

24
user3496846

いいえ、代わりにそれを行うことはできません。 unique_ptrを移動するとnullになります。そうでなかったら、それはユニークではないでしょう。もちろん、attachActorはこのような愚かなことをしないと仮定しています。

attachActor(std::unique_ptr<Tony>&&) {
    // take the unique_ptr by r-value reference,
    // and then don't move from it, leaving the
    // original intact
}

セクション20.8.1パラグラフ4。

さらに、u(unique_ptrオブジェクト)は、要求に応じて、所有権を別の一意のポインターu2に転送できます。そのような転送が完了すると、次の事後条件が成立します。
-u2.pは転送前のu.pと同じです。
-.pはnullptrと等しい
-転送前のu.dが状態を維持している場合、その状態はu2.dに転送されています。

27

標準では、std::unique_ptrの移動コンストラクターは(§20.8.1.2.1¶16、強調が追加されました)と書かれています。

unique_ptr(unique_ptr&& u) noexcept;

所有権の移動からuからunique_ptr*thisを構築します。

したがって、attachActorに引数として渡される一時オブジェクトを移動構築した後、tonyからtonyがオブジェクトを所有しなくなるため、tony.get() == nullptrになります。 (これは、標準ライブラリが実際に移動されたオブジェクトの状態についてアサーションを行う数少ないケースの1つです。)

ただし、参照を返すという欲求は、裸のnewおよび生のポインタに頼らずに満たすことができます。

Tony&
Movie::addTony()
{
  auto tony = std::make_unique<Tony>();
  auto p = tony.get();
  attachActor(std::move(tony));
  return *p;
}

このコードは、attachActorがその引数をフロアにドロップしないことを前提としています。それ以外の場合、ポインターpは、attachActorreturnedになった後にぶら下がります。これに依存できない場合は、インターフェイスを再設計し、代わりに共有ポインターを使用する必要があります。

std::shared_ptr<Tony>
Movie::addTony()
{
  auto tony = std::make_shared<Tony>();
  attachActor(tony);
  return tony;
}
11
5gon12eder