このコードは私がやりたいことです:
_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になりますか?検証できることは知っていますが、標準的なことは何ですか?
いいえ、代わりにそれを行うことはできません。 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に転送されています。
標準では、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
は、attachActor
がreturn
edになった後にぶら下がります。これに依存できない場合は、インターフェイスを再設計し、代わりに共有ポインターを使用する必要があります。
std::shared_ptr<Tony>
Movie::addTony()
{
auto tony = std::make_shared<Tony>();
attachActor(tony);
return tony;
}