Difference between std :: vector and std :: array initialization lists

This C ++ 11 code works fine for me:

#include <iostream> #include <vector> #include <array> using namespace std; struct str { int first, last; }; vector<str> fields { {1,2}, {3,4}, {5,6} }; int main() { for (str s : fields) cout << s.first << " " << s.last << endl; } 

It prints six expected values.

But if I change vector<str> to array<str,3> , gcc gives me this error: "too many initializers for" std :: array ".

If I changed the initialization of fields this way:

 array<str,3> fields { str{1,2}, str{3,4}, str{5,6} }; 

Everything works well.

So, why do I need str{1,2} when using std::array , but only {1,2} when using std::vector ?

+7
c ++ arrays c ++ 11 stdvector initializer-list
source share
2 answers

See the cppreference section in aggregate initialization .

Aggregate Initialization Effects:

  • Each element of the array or non-static member of the class in the index / appearance order of the array in the class definition is initialized by copying the corresponding section of the initializer list.

  • If the initializer clause is a nested list with a binding to completion, the corresponding class member is itself an aggregate: aggregate initialization is recursive.

This means that if you had your own population within your structure, for example:

 struct str { struct asdf { int first, last; } asdf; }; 

asdf will be initialized with the first nested parenthesis initialization list, i.e. { { 1, 2 } } . The reason you usually need two pairs of curly braces is because the nested list of anchor elements initializes the base aggregate in std::array (for example, T a[N] ).

However, you can still initialize your array as follows:

 array<str,3> fields { 1, 2, 3, 4, 5, 6 }; 

or

 array<str,3> fields { { 1, 2, 3, 4, 5, 6 } }; 

instead of this.

On the other hand, how you initialize your vector is covered by list initialization . std::vector has a constructor that takes std::initializer_list .

Effects of initializing a list of an object of type T:

  • Otherwise, the constructors T are considered in two phases:

    • All constructors that take std::initializer_list as a single argument, or as the first argument, if the rest of the default arguments are checked and matched by overload resolution against a single argument of type std::initializer_list

Please note that you cannot initialize your vector (for example:

 vector<str> fields { 1,2, 3,4, 5,6 }; 

but

 vector<int> fields { 1,2, 3,4, 5,6 }; 

fine.

+6
source share

This is because array initialization is built a little differently than vector.
To initialize an array, you need to use two curly braces.
Due to the syntax, you can skip it if you initialize only one object.
So everything is fine:

 array{1,2,3} -> array{{1,2,3}} 

But in your example, you initialize several objects so that the compiler does not add additional curly braces. Using two curly braces, this is a fix.

 array<str,3> fields {{ {1,2}, {3,4}, {5,6} }}; 
+4
source share

All Articles