统一初始化 是一项重要且有用的 C++11 功能。但是,您不能只使用 {}
无处不在:
std::vector<int> a(10, 0); // 10 elements of value zero
std::vector<int> b({10, 0}); // 2 elements of value 10 and 0 respectively
std::vector<int> c{10, 0}; // 2 elements of value 10 and 0 respectively
std::vector<int> d = {10, 0}; // 2 elements of value 10 and 0 respectively
auto e(0); // deduced type is int
auto f = 0; // deduced type is int
auto g{0}; // deduced type is std::initializer_list<int>
auto h = {0}; // deduced type is std::initializer_list<int>
注意到 聚合初始化 例如std::arrays
需要使用 {{}}
,在我看来,将选择哪个 vector 构造函数的整个问题都可以通过要求 {{}}
来避免。调用采用 std::initializer_list
的构造函数:
std::vector<int> i{10, 0}; // 10 elements of value zero
std::vector<int> j{{10, 0}}; // 2 elements of value 10 and 0 respectively
std::vector<int> k = {10, 0}; // 2 elements of value 10 and 0 respectively
auto l{0}; // deduced type is int
auto m{{0}}; // deduced type is std::initializer_list<int>
auto n = {0}; // deduced type is std::initializer_list<int>
我确定已经讨论过了,那么反对的理由是什么?首选来自标准提案的引述/链接作为答案。
更新。 — N2532 中有一点指出:
(3) The likely nasty ambiguity cases occur only for short initializer lists [...]
(5) Why should the language rules force programmers who wants terseness and ambiguity control (for perfectly good reasons) to write more to please programmers who prefer (for perfectly good reasons) to be more explicit – and can be?
[...]
Assume that a programmer expects f(X) to be called. How might a f(Y) “hijack” a call?
(4) Assume that X has no initializer-list constructor, but Y does. In this case, the priority given to initializer-list constructors favor the hijacker (remember we assumed that the programmer somehow expected f(X) to be called). This is analogous to someone expecting f(y) to invoke f(X) using a user-defined conversion and someone comes along with an f(Y) that matches exactly. I think it would be fair to expect that someone who uses {…} will remember the possibility of initializer-lists constructors. [emphasis mine]
我想关键在于可以,这意味着您不必使用统一初始化。使用 {}
正确很难,因为:
您不仅需要检查您要调用的构造函数,还需要检查采用
initializer_list
的任何 构造函数。可能会(并且可能会)战胜它;如果您使用
{}
编写代码将来有人会添加std::initializer_list
您的代码可能会破坏构造函数,悄悄地这样做。
即使你有一个类A
与构造函数A(int, bool)
和 A(std::initializer_list<double>)
, 后者将选择前者为 A a{0, false};
(IMO 是疯了),所以我发现真的很难在有或可能有的类上使用统一初始化(需要 Crystal 球超能力)initializer_list
构造函数。
您的代码可以悄无声息地破坏这一事实让我很担心。
最佳答案
以下是 Stroustrup 就此主题所说的话:
Uniform and universal was not designed to be just a 4th alternative. It was designed to be the initialization syntax,and was unfortunately [not] feasible to use with all legacy code, especially
vector
. Had I designedvector
today, you would have had to say something likevector<int> {Count{9}};
to get a count.
并回答“问题是 vector 还是 {}-init 语法?”这个问题
It's the vector design: Had I designed
vector
today, you would have had to say something likevector<int> {Count{9}};
to get a count.The more general problem is to have several semantically different arguments of the same type eventually leads to confusion, especially if they can appear adjectly. For example:
vector<int> v(7,2); // 7 (a count) element with the value 2
关于c++ - 为什么采用 std::initializer_list 的构造函数不首选双花括号语法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22501368/