値で返す必要があります。
この規格には、値による返却の効率を向上させる特定の機能があります。これは「コピー削除」と呼ばれ、より具体的には、この場合は「名前付き戻り値の最適化(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
ベクターを繰り返し呼び出す場合、このテンプレートベースのコードも同様に優れているはずです。
f
ませんか?