23

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

たとえば、std::vector<std::string>関数に a を渡すときは、常に次のオプションを検討します。

  1. ベクトル オブジェクトの状態を変更するつもりですが、関数の終了後にそれらの変更を反映させたくありません。つまり、コピーを作成します。

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

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

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

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

4

4 に答える 4

34

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

まったくコピーできませんunique_ptr。クラスの要点は、コピーできないことです。可能であれば、オブジェクトへの一意の(つまり、特異な) ポインターにはなりません。なんらかの参照形式で渡すか、移動する必要があります。

スマート ポインターは、それらが指すものの所有権に関するものです。誰がこの記憶を所有し、誰がそれを削除する責任を負うのか。unique_ptr一意の所有権を表します: ちょうど 1 つのコードがこのメモリを所有しています。所有権を ( 経由でmove) 譲渡することはできますが、その場合、メモリの所有権は失われます。shared_ptr共有所有権を表します。

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

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

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

于 2012-09-20T20:00:30.460 に答える
6

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

void function(std::string * ptr);

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

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

于 2012-09-20T20:14:34.080 に答える
5

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

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

  • いつものように渡しconst smartptr<T>&ます(ポインタを変更することはできませんが、ポインタが指している状態を変更することはできます)。
  • いつものように渡しsmartptr<T>&ます(また、ポインタを変更することもできます)。
  • as smartptr<T>(コピーによる) の受け渡しは、 smartptrがコピー可能な場合にのみ機能します。のように呼び出し時に「移動」しない限り、では機能しますstd::shared_ptrが、 では機能しません。したがって、 を無効にし、ポインターを渡されたパラメーターに移動します。(一時的な場合、移動は暗黙的であることに注意してください)。std::unique_ptrfunc(atd::move(myptr))myptrmyptr
  • smartptr<T>&&(move によって) as として渡すと、呼び出し時にポインターを移動する必要があり、明示的に使用する必要がありますstd::move(ただし、特定のポインターに意味を持たせるには "move" が必要です)。
于 2012-09-20T19:59:50.423 に答える