据我所知,uniform initialization是初始化对象的首选语法。 Herb Sutter writes
首先,它被称为“统一初始化”,因为它对所有类型都是相同的 - 包括聚合结构和数组以及std :: containers ......
以及this question州已接受的答案
除非你有充分的理由不这样做,否则首选{}初始化替代品。
但是,请考虑以下代码:
#define BRACES
template<typename V>
class foo {
public:
template<typename W>
explicit foo(const W &w) :
#ifdef BRACES
m_v{w}
#else // #ifdef BRACES
m_v(w)
#endif // #ifdef BRACES
{}
private:
V m_v;
};
struct bar{};
int main()
{
bar b;
foo<bar>{b};
#ifdef BRACES
bar c{b};
#else // #ifdef BRACES
bar c(b);
#endif // #ifdef BRACES
}
如果取消注释#define BRACES
,则此代码无法在行上使用error: too many initializers for ‘bar’
构建(g ++ 4.8.5)
m_v{w}
foo
的构造函数中的。这是有意义的,因为更直接的调用
bar c{b};
main
中的同样失败,它们基本相同(虽然模板代码不知道)。
相反,评论#define BRACES
会导致所有内容构建。这是否是在这种类型的模板代码中避免这种形式的初始化的指示?
修改
@ melak47指出这个问题没有出现在g ++ 5.1中,并且给了convincing proof。它显然在4.8.5和5.1之间消失了。
答案 0 :(得分:2)
当您尝试从相同类型的某些内容初始化聚合时,列表初始化不太有效。
这是CWG 1467,其解决方案(除其他事项外)为[dcl.init.list]/3中的巨型列表引入了另一个子弹以使其工作:
定义了
T
类型的对象或引用的列表初始化 如下:
- 如果
T
是类类型且初始值设定项列表包含 cvU
类型的单个元素,则其中U
为T
或一个派生自T
的类, object从该元素初始化(通过复制初始化) copy-list-initialization,或者直接初始化 直接一览初始化)。
答案 1 :(得分:-1)
当解析重载的构造函数时,在考虑其他重载的构造函数之前,braced初始化将使用std :: initializer_list参数匹配构造函数。所以
bar c{b};
将与采用std :: initializer_list的构造函数匹配,而不是生成的复制构造函数。
在第7项中讨论了这一点:在创建Scott Meyers的对象时,区分()和{}