web-dev-qa-db-ja.com

空の括弧付き初期リスト(値の初期化または初期化子リスト)によるリストの初期化と、「リスト」タイプの明示的なデフォルトの初期化

バックグラウンド

Scott MayersEffective C++のアイテム4に基づいて、適切な場合、 メンバー初期化リスト を介してカスタム型のすべてのメンバープロパティを初期化することをお勧めします(宣言と同じ順序)、アクセス可能なデフォルトのCTORを持つ非PODタイプの場合でも:.

[抜粋:スコットマイヤーズ。 「Effective C++ Third Edition 55プログラムとデザインを改善するための特定の方法。」]

項目4:オブジェクトが使用される前に初期化されていることを確認してください

...

組み込みタイプのオブジェクトの場合、初期化と割り当ての間にコストの違いはありませんが、一貫性を保つために、メンバーの初期化を介してすべてを初期化することがしばしば最適です。同様に、データメンバーをデフォルトで作成する場合でも、メンバー初期化リストを使用できます。初期化引数として何も指定しないでください。」

...しかし、初期化リストにすべてのデータメンバーを常にリストするというポリシーがあれば、省略された場合に初期化されない可能性があるデータメンバーを覚えておく必要がなくなります。

ここで、CTOR:sが std::initializer_list パラメータを受け入れる型を持つメンバー変数の場合、「リスト」自体に説明的な値があるw.r.tです。型(例:std::vector)。デフォルトの構築であっても、所有する型のメンバー初期化子リストの変数の明示的な初期化で空のbraced-init-listを使用することは価値があり、説明的です。

たとえば、空として初期化されるstd::vectorメンバーを持つカスタムタイプ。そのような状況で、次の3つのバリエーションを見ました(std::vectorメンバーのメンバー初期化リストを明示的に使用する状況で):

// A) Using std::vector:s default CTOR.
struct FooA {
  FooA() : numbers() {};
private:
  std::vector<int> numbers;
};

// B) Using an empty braced-init-list invoking value-initialization;
//    also using std::vector:s default CTOR.
struct FooB {
  FooB() : numbers{} {};
private:
  std::vector<int> numbers;
};

// C) Empty braced-init-list used to explicitly invoke std::vector:s
//    std::initialization_list CTOR.
struct FooC {
  FooC() : numbers({}) {};
private:
  std::vector<int> numbers;
};

空でないbraced-init-listを使用することの「説明的な値」は、空でない場合と比較すると明らかである可能性があります。

// D) Non-empty braced-init-list use to explicitly invoke std::vector:s
//    std::initialization_list CTOR.
struct FooD {
  FooD() : numbers({1, 2, 3}) {};
  /* or: 
  FooD() : numbers{1, 2, 3} {}; */
private:
  std::vector<int> numbers;
};

ご質問

  • [Q1]上記のA&BとCを比較すると、後者は優先されない可能性があります。空のリストを使用してstd::initializer_list CTORを明示的に呼び出すと、オーバーヘッドが発生しますか? (単にデフォルトのCTORを直接使用するのと比較して)。

  • [Q2]W.r.t.ベストプラクティス/表示の意図:「リスト」に直接の説明的な値がある場合は、明示的なデフォルトのCTOR呼び出し(A)よりも、空のbraced-init-list(B&C)を使用することをお勧めします初期化するタイプ(例:std::vector)に?それとも、タイプの「リストの関連付け」を説明することに重きを置かずに、デフォルトのCTOR(Aおよび可能なB)への呼び出しについて明示的にする方がよいでしょうか。


(これはSE-Software Engineeringでの私の最初の投稿です;うまくいけばそれは多少多分 on-topic ここにあります。それ以外の場合はアドバイスしてください)

3
dfri

「値の初期化」(_T{}_)と「たまたま空になっている値のリスト」(T({}))の違いについて効果的に話しています。私のベストプラクティスは、あなたの意図を最もよく表すことをすべきだと思います。

vectorを初期化する値とリストから値を初期化する値には違いがあり、たまたま空です。後者の場合、いつか1つまたは複数の要素をそのリストに追加できます。前者の場合、あなたはそうしません。したがって、コードの意味を最もよく表す方法を実行する必要があります。

効率の問題については、ほとんど問題ではありません。コードの明快さの観点から始める必要があります。パフォーマンスが問題になる場合は、後で調整できます。 「空のリスト」と「値の初期化」のどちらを選択するかは、何よりもまず意図を伝えることです。

4
Nicol Bolas