c++ - 为什么采用 std::initializer_list 的构造函数不首选双花括号语法

标签 c++ c++11 initializer-list uniform-initialization

统一初始化 是一项重要且有用的 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 designed vector today, you would have had to say something like vector<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 like vector<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/

相关文章:

c++ - std::initializer_list 和 c array [] 的优缺点是什么?

c++ - 为什么有不同的输入值?

c++ - 无法在数组 C++ 中找到最高/最低元素

c++ - 错误 : no viable overloaded operator[]

c++ - 什么时候应该使用 std::thread::joinable?

c++ - 使用表达式模板时,根据左值/右值提供类的不同实现

c++ - 对于字符串中的每个字符

c++ - 对类成员而不是 getter 的 Const 引用

c++ - 使用 C++ 用户定义的文字来初始化数组

C++ - 使用initializer_list作为参数的模板函数