コンストラクターと初期化リストの間で実行時間に違いはありますか?(またはコーディングの好みの問題ですか?)頻繁に作成する必要のあるオブジェクトのセットがあり、コンストラクターの代わりに初期化リストを使用することでパフォーマンスが向上するかどうかを知りたいです。
クラスAのインスタンスを100万個作成し、クラスBのインスタンスをさらに100万個作成する場合は、どちらを選択するのがよいでしょう(オブジェクトはネットワーク内で生成されたパケットを表すため、これらの番号です)。
class A {
private:
int a, b;
public:
A(int a_var, int b_var):a(a_var), b(b_var) {};
};
class B {
private:
int a, b;
public:
B(int a_var, int b_var) {
a = a_var;
b = b_var;
}
};
(例のように)プリミティブ型のコンストラクターのいずれかが他のコンストラクターよりも高速である場合、aとbを型に置き換えると、より高速になりますか?
タイプの例:
class AType {
private:
string a, b;
public:
AType(string a_var, string b_var):a(a_var), b(b_var) {};
};
違いは、クラスB
のコンパイラーによって呼び出される簡単なデフォルトコンストラクターのない型の場合です。クラスB
は次と同等です。
class B {
private:
SleepyInt a, b;
public:
// takes at least 20s
B(int a_var, int b_var) : a(), b()
// ^^^^^^^^^^
{
a = a_var;
b = b_var;
}
};
メンバー変数または基本クラスコンストラクターを初期化リストに配置しない場合、デフォルトのコンストラクターが呼び出されます。 int
は基本型であり、デフォルトのコンストラクターは無料です。したがって、例に違いはありませんが、より複雑な型の場合、コンストラクターと代入は単に構築するよりもコストがかかる可能性があります。
違いを説明するための面白い例:
class SleepyInt {
public:
SleepyInt () {
std::this_thread::sleep_for(std::chrono::milliseconds( 10000 ));
}
SleepyInt (int i) {}
SleepyInt & operator = (int i) { return *this; }
};
class A {
private:
SleepyInt a, b;
public:
A(int a_var, int b_var):a(a_var), b(b_var) {};
};
class B {
private:
SleepyInt a, b;
public:
// takes at least 20s
B(int a_var, int b_var) {
a = a_var;
b = b_var;
}
};
コンストラクターでの割り当てではなく、初期化リストを使用することは一般的に受け入れられている方法であり、それには非常に正当な理由があります。
初期化リストを使用して、POD(プレーンオールドデータ)とユーザー定義タイプの両方を初期化できます。 PODタイプを初期化する場合、効果は代入演算子とまったく同じです。つまり、PODタイプのコンストラクターでの初期化リストまたは代入の間にパフォーマンスの違いはありません。
非PODタイプを検討すると、物事はより興味深いものになります。コンストラクターが呼び出される前に、親クラスのコンストラクターが呼び出され、次に含まれているメンバーが呼び出されます。デフォルトでは、引数なしのコンストラクターが呼び出されます。初期化リストを使用して、呼び出すコンストラクターを選択できます。
したがって、質問に答えるために、パフォーマンスの違いがありますが、それは非PODタイプを初期化する場合のみです。
メンバーが多かれ少なかれ複雑なタイプである場合、割り当ての初期化により、最初にデフォルトのコンストラクター呼び出しが発生し、次にoperator=
、これには時間がかかる場合があります。