web-dev-qa-db-ja.com

スマートポインタを関数に渡すにはどうすればよいですか?

オブジェクトを関数に渡すとき、動的メモリを含む他のオブジェクトと同じルールがスマートポインタに適用されますか?

たとえば、私が合格すると、std::vector<std::string>関数に私は常に次のオプションを検討します。

  1. ベクトルオブジェクトの状態を変更しますが、しないでください関数の終了後にこれらの変更を反映させたいので、AKAはコピーを作成します。

    void function(std::vector<std::string> vec);
    
  2. ベクトルオブジェクトの状態を変更します。do関数の終了後にこれらの変更を反映させたいので、AKAは参照を作成します。

    void function(std::vector<std::string> & vec);
    
  3. このオブジェクトはかなり大きいので、参照を渡す方がよいですが、コンパイラーに変更させないように指示してください。

    void function(std::vector<std::string> const& vec);  
    

これはスマートポインタと同じロジックですか?そして、いつ移動セマンティクスを検討する必要がありますか?スマートポインタを渡す方法に関するいくつかのガイドラインは、私が最も望んでいるものです。

18
Trevor Hickey

スマートポインタにはポインタセマンティクスがあり、値セマンティクスではありません(まあ、あなたがそれを意味する方法ではありません)。 shared_ptr<T>T*と考えてください。それをそのように扱います(参照カウントと自動削除を除いて)。スマートポインタをコピーしても、それが指すオブジェクトはコピーされません。これは、T*をコピーしてもそれが指すTがコピーされないのと同じです。

unique_ptrをコピーすることはできません。クラスの要点は、それができないコピーされるということです。可能であれば、オブジェクトへの一意(つまり、単数)ポインタではありません。何らかの形の参照またはmoving itのいずれかで渡す必要があります。

スマートポインタはすべて、それらが指すものの所有権に関するものです。このメモリの所有者と削除の責任者。 unique_ptrは一意の所有権を表します。正確に1つのコードがこのメモリを所有します。 (moveを介して)所有権を譲渡できますが、そうすることで、メモリの所有権を失う譲渡できます。 shared_ptrは共有所有権を表します。

すべての場合において、パラメータリストでのスマートポインタの使用は所有権の譲渡を表します。したがって、関数がスマートポインターを受け取る場合、そのオブジェクトの所有権はclaimになります。関数が所有権を取得することになっていない場合は、スマートポインターを取得するべきではありません。参照(T&)を使用するか、null可能性が必要な場合は、ポインターを使用しますが、決して格納しないでください。

誰かにunique_ptrを渡す場合、あなたは所有権を与えるです。つまり、一意の所有権の性質上、あなたは失うメモリの所有権です。したがって、値以外の方法でunique_ptrを渡す理由はほとんどありません。

同様に、あるオブジェクトの所有権を共有したい場合は、shared_ptrを渡します。参照によって行うか、値によって行うかはあなた次第です。あなたは所有権を共有しているので、とにかく(おそらく)コピーを作成するので、価値によってそれを取る方がよいでしょう。この関数は、std::moveを使用して、クラスメンバーなどに移動できます。

24
Nicol Bolas

関数がポインターを変更またはコピーしない場合は、代わりにダムポインターを使用してください。スマートポインターはオブジェクトの存続期間を制御するために使用されますが、関数は存続期間を変更しないため、スマートポインターは必要ありません。また、ダムポインターを使用すると、呼び出し元が使用する型にある程度の柔軟性が得られます。

void function(std::string * ptr);

function(my_unique_ptr.get());
function(my_shared_ptr.get());
function(my_dumb_ptr);

unique_ptrはコピーできないため、渡す必要がある場合は参照を渡す必要があります。

4
Mark Ransom

スマートポインタは、その存続期間を管理する別のオブジェクトを参照するオブジェクトです。

スマートポインタを渡すには、スマートポイトナーがサポートするセマンティクスを尊重する必要があります。

  • _const smartptr<T>&_として渡すことは常に機能します(ポインターを変更することはできませんが、ポインターが指すものの状態を変更することはできます)。
  • _smartptr<T>&_として渡すことは常に機能します(そしてポインターを変更することもできます)。
  • _smartptr<T>_(コピーによる)として渡すことは、smartptrがコピー可能である場合にのみ機能します。 func(atd::move(myptr))のように呼び出し時に「移動」して、myptrを無効にし、ポインタをに移動しない限り、_std::shared_ptr_では機能しますが、_std::unique_ptr_では機能しません。渡されたパラメーター。 (myptrが一時的な場合、移動は暗黙的であることに注意してください)。
  • _smartptr<T>&&_(移動による)として渡すと、_std::move_を明示的に使用するように強制されるため、呼び出し時にポインターが移動されます(ただし、特定のポインターを理解するには「移動」が必要です)。
4