在构造函数中使用{}
而不是()
将允许我在标题中使用特定构造函数初始化类成员,如下所示:
class X {
private:
std::vector y{1, 2, 3};
};
但我怎么知道,对于课程Z
,我使用Z z{a, b};
会调用包含两个参数的构造函数 - Z::Z(int a, int b)
- 而不是std::initializer_list
?
我的意思是std::complex(1, 2)
和std::complex{1, 2}
相同,但std::vector(3)
和std::vector{3}
肯定不是。
我是否应始终使用{}
变体或使用()
,除非我需要{}
?
答案 0 :(得分:8)
这个主题可以涵盖整本书的章节。请参阅Scott Meyers撰写的this recent draft Item中他即将推出的有效现代C ++(为了清晰而重新格式化)的引用:
大多数开发人员最终选择一种分隔符作为默认值, 只在必要时使用另一个。
Braces-by-default人们被广泛的适用性所吸引, 他们对narrowing conversions的预防及其避免 C ++的most vexing parse。在某些情况下,这些人理解 (例如,创建具有给定大小和初始元素的
std::vector
值),括号是必需的。相比之下,走括号的人群将括号视为他们的 默认参数分隔符。他们被它的一致性所吸引 C ++ 98句法传统,它避免了 auto-deduced-a-
std::initializer_list
problem,以及那些知识 他们的对象创建调用不会是inadvertently waylaid bystd::initializer_list
constructors。他们有时只承认 大括号会做(例如,当创建具有特定的容器时) 值)。这两种方法都没有比其他方法更好。我的建议是 选择一个并一致地应用它。
答案 1 :(得分:1)
规则是,如果一个类的构造函数带有initializer_list
,并且 braced-init-list 中的元素是可转换的(请记住braced-init-lists确实如此)不允许缩小转换次数到initializer_list
的参数类型,然后调用initializer_list
的构造函数将始终。否则,编译器将尝试匹配其他构造函数。
如果是空的braced-init-list,则调用默认构造函数,假设一个可访问。
对于初始化,关于圆括号是否应优先于括号,反之亦然,您的问题没有简单的答案。事后看来,vector
的构造函数是一个糟糕的设计选择,因为它可以让人意想不到地表现,至少对于没有经验的人来说是非常琐碎的。