明白な答えは正しく、基本的に最適です。
void do_stufF(std::vector<int>& on_this); // (1)
std::vector<int> do_stuff_better() { // (2)
std::vector<int> myVector_temp; // (3)
do_stuff(myVector_temp); // (4)
return myVector_temp; // (5)
}
(3)では、自動ストレージ (スタック上) に名前付きの戻り値を作成します。
(5)では、関数から名前付きの戻り値のみを返し、その名前付きの戻り値以外を関数内の他の場所で返すことはありません。
(3)と(5)のおかげで、コンパイラはmyVector_temp
オブジェクトの存在を除外することができます (おそらくそうするでしょう) 。関数の戻り値を直接構築し、それを呼び出します myVector_temp
。既存の移動コンストラクターまたはコピー コンストラクターが必要ですが、それは呼び出されません。
一方、 を呼び出すときdo_stuff_better
、一部のコンパイラは呼び出し時に割り当てを省略することもできます。
std::vector<int> bob = do_stuff_better(); // (6)
コンパイラは、「bob へのポインター」を効果的に渡し、do_stuff_better()
その戻り値をbob
の場所に構築するように指示し、このコピー構築も省略できます (構築するようにdo_stuff_better()
要求された場所が呼び出されるように、呼び出しがどのように発生するかを調整できます)。の戻り値は の場所と同じですbob
)。
また、C++11 では、両方の elision の要件が満たされていない場合、またはコンパイラがそれらを使用しないことを選択した場合でも、どちらの場合も a のmove
代わりに a を実行する必要がありますcopy
。
行(5)では、ローカルで宣言された自動保存期間変数をプレーンでシンプルなreturn
ステートメントで返しています。move
これにより、省略されていない場合は戻り値が暗黙になります。
行(6)で、関数は右辺値である名前のないオブジェクトを返します。bob
それから を構築する場合は、構築しmove
ます。
move
ing astd::vector
は、〜3つのポインターの値をコピーしてから、その大きさに関係なくソースをゼロにすることで構成されvector
ます。要素をコピーまたは移動する必要はありません。
内の名前付きローカル変数を削除し、 の値do_stuff_better()
を削除して代わりに を直接構築する上記の両方の省略は、いくぶん脆弱です。コンパイラがこれらの省略を実行できるルールと、コンパイラが実際に省略を実行する状況を学ぶことは価値があります。return
do_stuff_better()
bob
壊れやすい例として、エラー状態を確認した後return std::vector<int>()
に inを実行したブランチがある場合do_stuff_better()
、関数内の省略はおそらくブロックされます。
省略がブロックされていたり、コンパイラがそれを実装していない場合でも、コンテナーが実行されるという事実はmove
、実行時間のコストが最小限になることを意味します。