値で返す必要があります。
標準には、値による返品の効率を向上させる特定の機能があります。これは「コピー省略」と呼ばれ、より具体的には、この場合は「名前付き戻り値の最適化 (NRVO)」と呼ばれます。
コンパイラはそれを実装する必要はありませんが、コンパイラは関数のインライン化を実装する (または最適化をまったく実行する) 必要はありません。しかし、コンパイラが最適化しない場合、標準ライブラリのパフォーマンスはかなり低下する可能性があり、すべての本格的なコンパイラはインライン化と NRVO (およびその他の最適化) を実装しています。
NRVO が適用されると、次のコードではコピーが行われません。
std::vector<int> f() {
std::vector<int> result;
... populate the vector ...
return result;
}
std::vector<int> myvec = f();
しかし、ユーザーはこれをしたいかもしれません:
std::vector<int> myvec;
... some time later ...
myvec = f();
初期化ではなく代入であるため、コピー省略はここでのコピーを妨げません。ただし、値で返す必要があります。C++11 では、代入は「移動セマンティクス」と呼ばれる別のものによって最適化されます。C++03 では、上記のコードはコピーを引き起こします。理論的にはオプティマイザーでコピーを回避できるかもしれませんが、実際には難しすぎます。の代わりにmyvec = f()
、C++03 では次のように記述します。
std::vector<int> myvec;
... some time later ...
f().swap(myvec);
ユーザーにより柔軟なインターフェースを提供する別のオプションがあります。
template <typename OutputIterator> void f(OutputIterator it) {
... write elements to the iterator like this ...
*it++ = 0;
*it++ = 1;
}
さらに、既存のベクターベースのインターフェースをサポートすることもできます。
std::vector<int> f() {
std::vector<int> result;
f(std::back_inserter(result));
return result;
}
これは、既存のコードが前もって固定量よりも複雑な方法で使用している場合、既存のコードよりも効率が悪い可能性があります。reserve()
ただし、既存のコードが基本的push_back
にベクトルを繰り返し呼び出す場合は、このテンプレート ベースのコードも同様に優れているはずです。