【发布时间】:2014-03-15 17:35:55
【问题描述】:
C++11 引入了 {} 样式的初始化。但是这两种形式吗
T x {...};
T x = {...};
一样吗?
【问题讨论】:
-
据我所知,是的
标签: c++ c++11 uniform-initialization list-initialization
C++11 引入了 {} 样式的初始化。但是这两种形式吗
T x {...};
T x = {...};
一样吗?
【问题讨论】:
标签: c++ c++11 uniform-initialization list-initialization
它们并不完全相同。也许这可以通过一个反例来说明:
struct Foo
{
explicit Foo(std::initializer_list<int>) {}
};
int main()
{
Foo f0{1, 2, 3}; // OK
Foo f1 = {1, 2, 3}; // ERROR
}
因此,第二个变体要求类型可以从初始化列表隐式构造,而第一个版本则不需要。请注意,这同样适用于 Foo(int, int, int) 形式的构造函数。我随意选择了initializer_list<int>作为例子。
这将影响某些遵循“显式无处不在”理念编写的类型(人们在 C++03 代码中标记了多参数构造函数 explicit,即使在该标准中没有任何意义。)
【讨论】:
std::array<T,0> a = {};(不是错误但可能会发出警告)而std::array<T,0> a{{}};是必要的。聚合类型还有其他区别吗?
std::array<T,0> a = {}; 和 std::array<T,0> a{}; 都应该没问题。你用的是什么编译器?
std::array<int,2> a = {1, 2}; 与 std::array<int,2> b{{1, 2}};。在后者中需要双括号。
std::array<int,2> b{1, 2}; 有效并且适用于所有编译器,那么std::array<T,0> 就没有理由不为空,对吧?见Why is std::array< T, 0 > not empty?
除了 juanchopanza 的 answer 中解释的区别之外,direct-list-initialization 和 copy-list-initialization 之间还有另一个区别,即重大更改当涉及到auto 并键入 braced-init-list 的推断。虽然是not added as part of C++14(最后一个问答项目),但问题已经确定,何时实施由委员会决定。
例如,
auto foo = {42}; // deduces foo as an initializer_list<int>
auto foo{42}; // deduces foo as an int
所以直接列表初始化永远不会从参数中推断出initializer_list。因此,以下将是不正确的。
auto foo{1,2}; // cannot have multiple initializers for
// direct-list-initialization when deducing type
但这没关系:
auto foo = {1,2}; // copy-list-initialization still deduces initializer_list<int>
这同样适用于 lambda 表达式中的广义捕获。引用N3912
[x{5}](){}; // x is int
[x{1,2}](){}; // ill-formed, no multiple initializers with direct-init
[x = {5}](){}; // ok, x is an initializer_list<int> with one element
[x = {1,2}](){}; // ok, x is an initializer_list<int> with two elements
【讨论】:
语法在一种情况下使用它们意味着不同的东西
struct A { };
namespace X {
struct A final {};
struct A final = {};
}
在第一种情况下,我们定义了一个名为A 的结构,在第二种情况下,我们定义了一个名为final 的对象。
【讨论】: