C ++ 11でオブジェクトメンバー変数を初期化するこれらの方法の違いは何ですか?別の方法はありますか?どちらが良いですか(パフォーマンス)?:
class any {
public:
obj s = obj("value");
any(){}
};
または
class any {
public:
obj s;
any(): s("value"){}
};
ありがとう。
いいえ、これらは同じではありません。
それらの違いは、直接初期化とコピー初期化に適用されるものと同じです。これは微妙ですが、非常に混乱することがよくあります。
§12.6.2[class.base.init]:
mem-initializerのexpression-listまたはbraced-init-listは、直接初期化の8.5の初期化規則に従って、指定されたサブオブジェクト(または、委任コンストラクターの場合は完全なクラスオブジェクト)を初期化するために使用されます。[...]
非委任コンストラクターで、特定の非静的データメンバーまたは基本クラスがmem-initializer-idで指定されていない場合(コンストラクターにctor-initializerがないためにmem-initializer-listがない場合を含む)エンティティが抽象クラス(10.4)の仮想基本クラスではない場合、
—エンティティが中括弧または等しい初期化子を持つ非静的データメンバーである場合、エンティティは8.5で指定されているように初期化されます。
§8.5[dcl.init]:
フォームで発生する初期化
T x = a;
引数の受け渡し、関数の戻り、例外のスロー(15.1)、例外の処理(15.3)、および集計メンバーの初期化(8.5.1)は、コピー初期化と呼ばれます。
member-initializer-listで非静的データメンバーを初期化することは、直接初期化のルールに従います。これは、移動/コピーする必要のある中間の一時データを作成しません(コピーの省略なしでコンパイルされた場合)。データメンバーはコピー可能/移動可能である必要があります(コピーが省略されている場合でも)。さらに、直接初期化は明示的なコンテキストを導入しますが、コピー初期化は非明示的です(初期化用に選択されたコンストラクターがのexplicit
場合、プログラムはコンパイルされません)。
言い換えると、次のobj s = obj("value");
ようobj
に宣言されている場合、構文はコンパイルされません。
struct obj
{
obj(std::string) {}
obj(const obj&) = delete;
};
または:
struct obj
{
obj(std::string) {}
explicit obj(const obj&) {}
};
より具体的な例として、以下はコンパイルされませんが:
struct any
{
std::atomic<int> a = std::atomic<int>(1); // ill-formed: non-copyable/non-movable
std::atomic<int> b = 2; // ill-formed: explicit constructor selected
};
これは:
struct any
{
std::atomic<int> a;
std::atomic<int> b{ 2 };
any() : a(1) {}
};
どちらが良いですか(パフォーマンス)?
でコピーエリジオンが有効になって両方の同一の性能を有します。でコピーエリジオンが無効になって、すべてのインスタンス作成時の追加コピー/移動のコンストラクタ呼び出しがあり、コピーの初期化(構文が使用されているobj s = obj("value");
の一つである)が。
別の方法はありますか?
ブレース-OR-等しい初期化構文は、1つの実行を可能にするダイレクト・リストの初期化をも。
class any {
public:
obj s{ "value" };
any() {}
};
他に違いはありますか?
言及する価値のある他のいくつかの違いは次のとおりです。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加