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