Is initializing with “var{args}” a new feature of C++0x, or merely syntactic sugar?

你离开我真会死。 提交于 2019-12-04 04:19:58

问题


I was reading the C++0x faq and came across the section detailing initializer lists. The examples were mostly variations of:

vector<int> vi = { 1, 2, 3 };
vector<int> vj({1, 2, 3});
// etc.

However, also listed was the form:

vector<int> vk{2};

This form appears elsewhere in the faq, and I am curious as to whether it is semantically different from the initial two forms, or just syntactic sugar for vk({x, y, z}).


回答1:


One is uniform initialization, and the other is initializer lists. They are two different things, although as you can see, they can produce similar syntax.

vector<int> vk{2};

is a uniform initialization- the other two are initializer lists.




回答2:


The ({1, 2, 3}) form calls the constructors of vector<int> directly, and passes as first argument a {1, 2, 3}. You could have passed more arguments

vector<int> vk({1, 2, 3}, myAllocator);

If vector<int> would not have a constructor whose first parameter is an initializer_list or of another type that could be initialized by {1, 2, 3} (like, another container class), it would not work. In your case it works because vector<int> in fact has a constructor whose first parameter is a initializer_list<int>. This is just like in normal function calls

void f(vector<int> const& vk);
int main() { f({1, 2, 3}); }

If you omit the parentheses, as in vector<int> vk{1, 2, 3}, the exact meaning depends on the class. A vector<int> has an initializer list constructor, which is a constructor with a first parameter of type initializer_list<int> (optionally a reference to it), and all other params with default arguments. If the class has such a constructor, then the initializer list is passed to that constructor. Alternatively the class could simply be an aggregate (like struct A { int a; int b; int c; };, the initializer list would then init the members) or have a constructor that accepts 3 separate int arguments.

Finally the = { 1, 2, 3 } form is almost identical to the version omitting the parentheses (i.e just removing =), except that it forbids to use explicit constructors (i.e had they declared it as explicit vector(initializer_list<int>); or had they declared a explicit vector(int, int, int); instead, it would result in an error if you use = { 1, 2, 3 }).




回答3:


The uniform initialization prevents narrowing conversions i.e. conversions that would cause loss of data:

#include <vector>

std::vector<float> v{1.0F, 2.0F, 3.0F}; // OK: 

std::vector<float> w{1.0, 2.0, 3.0}; // OK: doubles could be put into floats without loss.

std::vector<int> j{1.1, 2.2, 3.3}; // error: narrowing

std::vector<int> k{1L, 2L, 3L}; // OK: the long numbers can be represented as int without loss.

std::vector<int> l{0xfacebeefL, 0xdeadbabeL, 0xfadecabeL}; // error: narrowing.


来源:https://stackoverflow.com/questions/7044281/is-initializing-with-varargs-a-new-feature-of-c0x-or-merely-syntactic-sug

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!