46

What is the actual benefit and purpose of initializer_list, for unknown number of parameters? Why not just use vector and be done with it?

In fact, it sounds like just a vector with another name. Why bother?

The only "benefit" I see of initializer_list is that it has const elements, but that doesn't seem to be a reason enough to invent this whole new type. (You can just use a const vector after all.)

So, what am I mising?

4

3 に答える 3

48

これは、プログラマーとコンパイラーの間の一種の契約です。プログラマーが と言うと、コンパイラーはそれから、同じ要素のシーケンスを含む{1,2,3,4}型のオブジェクトを作成します。initializer_list<int>このコントラクトは、コンパイラの実装に対する言語仕様によって課される要件です。

つまり、そのようなオブジェクトを手動で作成するのはプログラマではなく、オブジェクトを作成し、そのオブジェクトをinitializer_list<int>引数として取る関数に渡すのはコンパイラです。

実装はこのstd::vectorコントラクトを利用するinitializer_list<T>ため、引数として受け取るコンストラクターを定義し、initializer-list の要素で自分自身を初期化できるようにします。

しばらくの間、引数として取るコンストラクターがないと仮定すると、次のようになりstd::vectorます。std::initializer_list<T>

 void f(std::initializer_list<int> const &items);
 void g(std::vector<int> const &items);

 f({1,2,3,4}); //okay
 g({1,2,3,4}); //error (as per the assumption)

仮定によると、引数として受け取るstd::vectorコンストラクターがないため、コンパイラーはout のインスタンスを直接式から作成できないため、上記のように引数として渡すことができないことを意味します。これは、プログラマーとコンパイラーの間でそのような契約が作成されず、言語によって課されるためです。それを通して、表現から自分自身を創造することができます。std::initializer_list<T>{1,2,3,4}g()std::vector{1,2,3,4} std::initializer_liststd::vector{1,2,3,4}

std::initializer_listの形式の式が必要な場合はどこでも を使用できることがわかります{value1, value2, ...., valueN}。そのため、標準ライブラリの他のコンテナもstd::initializer_list、引数として取るコンストラクタを定義しています。このように、 の形式の式から構築するために他のコンテナに依存するコンテナはありません{value1, value2, ...., valueN}

それが役立つことを願っています。

于 2013-01-19T13:36:39.390 に答える
19

まあ、明らかstd::vector initializer_listそれ自体を使用できないため、その構文を取得するために使用する必要があります。

とにかく、initializer_list非常に軽量であることを意図しています。最適な保管場所を使用し、不要なコピーを防ぐことができます。を使用vectorすると、常にヒープ割り当てを取得し、必要以上のコピー/移動を取得する可能性が高くなります。

また、構文には明らかな違いがあります。そのようなものの 1 つがテンプレート型推論です。

struct foo {
    template<typename T>  
    foo(std::initializer_list<T>) {}
};

foo x{1,2,3}; // works

vectorここでは機能しません。

于 2013-01-19T13:30:43.013 に答える
12

initializer_listoverの最大の利点は、リストを作成するための専用の処理を必要とせずに、特定の要素シーケンスをインプレースvectorで指定できることです。

これにより、どの要素がベクターにプッシュされるかが正確にわかっている場合でも、初期化のために複数の呼び出しpush_back(またはforサイクル)を設定する必要がなくなります。vector

実際、それ自体には、より便利な初期化vectorのためにを受け入れるコンストラクターがあります。initializer_list2つのコンテナは補完的だと思います。

// v is constructed by passing an initializer_list in input
std::vector<std::string> v = {"hello", "cruel", "world"};

もちろん、initializer_listいくつかの制限(変換を絞り込むことは許可されていません)があり、場合によっては使用が不適切または不可能になる可能性があるという事実に注意することが重要です。

于 2013-01-19T13:40:12.527 に答える