スマートポインタを値で返します。
すでに述べたように、参照によってそれを返す場合、参照カウントを適切にインクリメントしないため、不適切なときに何かを削除するリスクが生じます。それだけで、参照によって戻らない十分な理由になるはずです。インターフェイスは堅牢でなければなりません。
戻り値の最適化(RVO)のおかげで、最近のコストの懸念は根本的ではないため、インクリメント、インクリメント、デクリメントのシーケンスなど、最新のコンパイラーでは発生しません。したがって、aを返す最善の方法shared_ptr
は、単に値で返すことです。
shared_ptr<T> Foo()
{
return shared_ptr<T>(/* acquire something */);
};
これは、最新のC ++コンパイラにとっては明らかに明白なRVOの機会です。すべての最適化がオフになっている場合でも、Visual C ++コンパイラーがRVOを実装していることは知っています。また、C ++ 11の移動セマンティクスでは、この懸念はさらに重要ではなくなります。(しかし、確実にする唯一の方法は、プロファイルを作成して実験することです。)
それでも確信が持てない場合は、Dave Abrahamsが、値で返すことを主張する記事を公開しています。ここでスニペットを複製します。記事全体を読むことを強くお勧めします。
正直に言うと、次のコードはどのように感じますか?
std::vector<std::string> get_names();
...
std::vector<std::string> const names = get_names();
正直なところ、私はもっとよく知っているべきですが、それは私を緊張させます。原則的に、ときget_names()
に戻り、我々はコピーする必要がありvector
のstring
秒。次に、を初期化するときに再度コピーする
names
必要があり、最初のコピーを破棄する必要があります。string
ベクトルにNがある場合、文字列の内容がコピーされるため、コピーごとにN + 1ものメモリ割り当てと、キャッシュに適さない大量のデータアクセスが必要になる可能性があります。
私はそのような不安に立ち向かうのではなく、不要なコピーを避けるために、参照渡しに頼ることがよくあります。
get_names(std::vector<std::string>& out_param );
...
std::vector<std::string> names;
get_names( names );
残念ながら、このアプローチは理想からほど遠いです。
- コードは150%増加しました
const
名前を変更しているため、-ness を削除する必要がありました。
- 関数型プログラマーが私たちに思い出させたいように、ミューテーションは、参照の透明性と方程式の推論を損なうことによって、コードを推論することをより複雑にします。
- 名前の厳密な値のセマンティクスはなくなりました。
しかし、効率を上げるためにこの方法でコードをめちゃくちゃにすることが本当に必要なのでしょうか?幸い、答えはノー(特にC ++ 0xを使用している場合はノー)です。