统一初始化是一个重要且有用的 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>
注意到在 eg 上的聚合初始化std::arrays
需要使用{{}}
,在我看来,通过要求 a调用构造函数采用 a ,可以避免选择向量构造函数的整个问题:{{}}
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) 可能的令人讨厌的歧义情况仅发生在简短的初始化列表 [...]
(5) 为什么语言规则要强迫想要简洁和多义性控制(出于非常好的理由)的程序员写更多的东西来取悦那些喜欢(出于非常好的理由)更明确的程序员——并且可以这样做?
[...]
假设程序员期望调用 f(X)。af(Y) 如何“劫持”一个电话?
(4) 假设 X 没有初始化列表构造函数,但 Y 有。在这种情况下,赋予初始化列表构造函数的优先级有利于劫持者(请记住,我们假设程序员以某种方式期望调用 f(X))。这类似于有人期望 f(y) 使用用户定义的转换来调用 f(X) 并且有人附带一个完全匹配的 f(Y)。我认为期望使用 {...} 的人会记住初始化列表构造函数的可能性是公平的。[强调我的]
我想关键在于can be,这意味着您不必使用统一初始化。正确使用{}
很难,因为:
您不仅要检查要调用的构造函数,还要检查任何构造函数,
initializer_list
它可能会赢得(并且可能会)胜过它;如果您使用编写代码
{}
并且将来有人添加了std::initializer_list
构造函数,则您的代码可能会中断并这样做默默地这样做。
即使你有一个A
带有构造函数的类A(int, bool)
and A(std::initializer_list<double>)
,后者将被选择而不是前者A a{0, false};
(IMO 是疯了),所以我觉得它真的在具有或可能具有的类上使用统一初始化困难(需要水晶球超级大国)initializer_list
构造函数。
您的代码可以默默地破坏这一事实让我很担心。