通常のコンパイラ最適化が有効になっていると仮定すると、以下に発生するコピー/オブジェクトの数。
std::vector<MyClass> v;
v.push_back(MyClass());
正確に1つのオブジェクトの作成と0のコピーではない場合、それを達成するために何ができますか(の変更を含むMyClass
)。本当に必要なのはそれだけだと私には思えます。
通常のコンパイラ最適化が有効になっていると仮定すると、以下に発生するコピー/オブジェクトの数。
std::vector<MyClass> v;
v.push_back(MyClass());
正確に1つのオブジェクトの作成と0のコピーではない場合、それを達成するために何ができますか(の変更を含むMyClass
)。本当に必要なのはそれだけだと私には思えます。
のコンストラクタにMyClass
副作用がある場合、C++03ではコピーを削除することは許可されていません。これは、コピーのソースである一時オブジェクトが参照(のパラメーターpush_back
)にバインドされているためです。
のコピーコンストラクタにMyClass
副作用がない場合、コンパイラは「as-if」ルールの下でそれを最適化することが許可されます。「通常の最適化」で実際に行われたかどうかを判断する唯一の賢明な方法は、発行されたコードを検査することだと思います。人々によって、何が正常であるかについて異なる考えがあり、特定のコンパイラは、の詳細に敏感である可能性がありMyClass
ます。私の推測では、これが意味するのは、コンパイラー(またはリンカー)が目に見えるすべてのものをインライン化するかどうかです。そうであれば、おそらく最適化されますが、そうでない場合は、最適化されません。したがって、コンストラクターコードのサイズでさえ関連性があるかもしれませんが、それが何をするかは気にしないでください。
したがって、あなたができる主なことは、デフォルトとのコピーコンストラクターの両方にMyClass
副作用がなく、インライン化できるようにすることだと思います。それらが利用できない場合、もちろんコンパイラーはそれらが副作用を持っている可能性があると想定し、コピーを実行します。リンク時の最適化が通常のコンパイラオプションである場合、それらを利用可能にするために多くのことを行う必要はありません。それ以外の場合、ユーザー定義の場合は、を定義するヘッダーファイルで実行しますMyClass
。特定の種類の副作用を持つデフォルトのコンストラクターを回避できる場合があります。一時的なアドレスがベクトル要素のアドレスと異なることに影響が依存しない場合でも、「as-if」が適用されます。
C ++ 11では、動きがあります(副作用がある場合は、同様に省略してはなりません)が、それv.emplace_back()
を回避するために使用できます。ムーブは、ムーブコンストラクターがMyClass
あればそれを呼び出します。それ以外の場合はコピーコンストラクターを呼び出します。上記の「as-if」についてのすべてがムーブに適用されます。emplace_back()
no-argsコンストラクターを呼び出して、ベクトル要素を構築します(または、引数を渡すとemplace_back
、それらの引数に一致するコンストラクターがあれば)、これはまさにあなたが望むものだと思います。
もしかして:
std::vector<MyClass> v;
v.push_back(MyClass());
なし。一時的に、push_backの移動バージョンが呼び出されます。移動構造でさえ、おそらく排除されるでしょう。
C ++ 11コンパイラを使用している場合は、emplace_backを使用して、ベクトルの最後に要素を作成できます。コピーは必要ありません。
C ++ 03では、構造とコピーに加えて、一時的なものの破棄があります。
コンパイラがC++11をサポートし、MyClassがmoveコンストラクターを定義している場合、1つの構文と1つのmoveがあります。
Timboが述べたように、emplace_backを使用して、オブジェクトがインプレースで構築されている移動を回避することもできます。