web-dev-qa-db-ja.com

参照によるスマートポインタの受け渡し

スマートポインタは一般に小さいので、値を渡すことは問題ではありませんが、それらへの参照を渡すことに問題はありますか。というか、これをしてはいけない特定のケースはありますか?

私はラッパーライブラリを作成していて、いくつかのクラスは基になるライブラリでスマートポインタオブジェクトをラップしています...私のクラスはスマートポインタではありませんが、APIは現在スマートポインタオブジェクトを値で渡します。

例:現在のコード:

void class::method(const AnimalPtr pAnimal) { ... }

になります

void class::method(const MyAnimal &animal){...}

ここで、MyAnimalは、AnimalPtrをカプセル化する新しいラッパークラスです。

ラッパークラスがいつかスマートポインターをラップする以上に成長しないという保証はないので、値を渡すと緊張します。

20
Mr. Boy

ほとんどの場合、shouldは、値ではなく参照によって共有ポインタを渡します。 std::shared_ptrのサイズは小さいですが、コピーのコストにはアトミック操作が含まれます(概念的には、コピーの破棄時にアトミックインクリメントとアトミックデクリメントが行われますが、一部の実装では非アトミックインクリメントを実行できると思います。 )。

他の場合、たとえばstd::unique_ptrは、copyが移動である必要があり、それが明確にドキュメントオブジェクトの所有権が関数に転送されます(所有権を転送したくない場合は、ではなく実際のオブジェクトへの参照を渡しますstd::unique_ptr)。

その他の場合、マイレージは異なる場合があります。スマートポインタのコピーのセマンティクスが何であるか、およびコストを支払う必要があるかどうかを知っておく必要があります。

コンストラクターへの場合を除いて、参照によってスマートポインターを渡すことは問題ありません。コンストラクターでは、元のオブジェクトへの参照を格納することができます。これは、スマートポインターのコントラクトに違反します。そうすると、メモリが破損する可能性があります。コンストラクターが今日参照を格納していなくても、コードが変更されるため、私はまだ警戒します。後で変数をより長く保持する必要があると判断した場合、見逃しがちです。

通常の関数では、初期化中に参照を設定する必要があるため、関数パラメーターを参照としてどこにも保存できません。参照を長寿命の非参照変数に割り当てることもできますが、それはコピーであるため、その寿命が適切に長くなります。したがって、どちらの場合でも、呼び出し元の関数がそれを解放した可能性があるときに、それを保持することはできませんでした。この場合、リファレンスを使用するとパフォーマンスが少し向上する可能性がありますが、ほとんどの場合、それに気付くつもりはありません。

つまり、コンストラクターは常に値を渡します。他の関数は、必要に応じて参照渡しします。

3
JoshG79