Question:
This code compiles:
#include <vector>
int main(int argc, char* argv[])
{
std::vector<int> v2 = { { {} } };
std::vector<int> v3 { { {} } };
std::vector<int> v4 { { { 1 } } };
std::vector<int> v5 ({ { { 1 } } });
return 0;
}
Why? How are multiple curly braces interpreted? If there was one pair of parentheses, it would be the initializer_list. And what are the three pairs of parentheses converted to? And why exactly three and not more (in GCC)? (Visual Studio 2013 allows an arbitrary number of parentheses in this situation.)
Answer:
All variants use the std::vector<int>
constructor, which initializes it from std::intializer_list<int>
, and the fourth alternative then uses the vector copy constructor.
In this case, the presence or absence of =
in the syntax of the initialization sheet in the first three options does not play a role, i.e. there is no difference in the semantics of the first two options.
-
Option
std::vector<int> v2 = { { {} } };
similar
std::intializer_list<int> temp_list = { {} }; std::vector<int> v2 = { temp_list };
In this case,
{}
is a valid initializer for an object of typeint
, i.e.std::intializer_list<int> temp_list = { {} };
in turn, similarly simply
int temp_int = {}; // инициализация нулем std::intializer_list<int> temp_list = { temp_int };
-
Option
std::vector<int> v3 { { {} } };
this, as mentioned above, is the same, only in the direct sheet-initialization syntax.
-
In the variant
std::vector<int> v4 { { { 1 } } };
{ 1 }
is a perfectly valid initializer for an object of typeint
. Those. this option is the sameint temp_int = { 1 }; std::intializer_list<int> temp_list = { temp_int }; std::vector<int> v4 = { temp_list };
-
And here is an option
std::vector<int> v5 ({ { { 1 } } });
already uses the copy constructor of the
std::vector<int>
class, i.e. similarstd::vector<int> temp_vector = { { { 1 } } }; // см. вариант 3 std::vector<int> v5(temp_vector);
For example, if we declare an artificial class
struct S { S(std::initializer_list<int> l) {} S(const S&) = delete; };
then the first three options will compile perfectly for it, but the fourth one will refuse to compile due to the remote copy constructor.
Attempts to increase the number of brackets lead to the formation of an incorrect initializer at the lowest level: neither { {} }
nor { { 1 } }
are already valid initializers for an object of type int
. So the code doesn't compile. By the way, VS2015 also refuses to compile options with an increased number of brackets.