【问题标题】:Why is the C++ initializer_list behavior for std::vector and std::array different?为什么 std::vector 和 std::array 的 C++ initializer_list 行为不同?
【发布时间】:2012-07-09 03:34:27
【问题描述】:

代码:

std::vector<int> x{1,2,3,4};
std::array<int, 4> y{{1,2,3,4}};

为什么 std::array 需要双花括号?

【问题讨论】:

  • std::array 是否真的需要第二组大括号,或者您只是收到警告? std::array&lt;int,4&gt; y{1,2,3,4}; 为我工作。
  • @bames53: GCC 编译错误。
  • @Xeo:编译带有警告的格式错误的程序并不是“错误”。
  • @Steve:确实如此。比方说非便携式?
  • @Xeo:是的,无论如何我都使用-Werror 来编写我编写的代码,所以它不会损害我的可移植性。其他人的里程可能会有所不同,如果他们是轻量级或需要包含由轻量级编写的头文件:-)

标签: c++ stl c++11


【解决方案1】:

std::array&lt;T, N&gt; 是一个聚合:它没有任何用户声明的构造函数,甚至没有一个采用std::initializer_list 的构造函数。使用大括号进行初始化是使用 聚合初始化 执行的,这是从 C 继承的 C++ 的一个特性。

聚合初始化的“旧式”使用=

std::array<int, 4> y = { { 1, 2, 3, 4 } };

使用这种旧式的聚合初始化,多余的大括号可能会被省略,所以这相当于:

std::array<int, 4> y = { 1, 2, 3, 4 };

但是,这些额外的大括号只能在“T x = { a }; 形式的声明中”(C++11 §8.5.1/11)被省略,也就是说,当使用旧样式 = 时。此允许大括号省略的规则不适用于直接列表初始化。这里有一个脚注:“在列表初始化的其他用途中不能省略大括号。”

有一个关于此限制的缺陷报告:CWG defect #1270。如果提议的解决方案被采纳,其他形式的列表初始化将允许大括号省略,并且以下将是格式良好的:

std::array<int, 4> y{ 1, 2, 3, 4 };

(向 Ville Voutilainen 致敬,感谢他查找缺陷报告。)

【讨论】:

  • 所以这是为array呈现的抽象模型的失败?
  • @Mehrdad:它统一的。 不是统一的是您正在初始化两种完全不同的类型。
  • @NicolBolas:我认为统一的重点是对不同类型使用相同的初始化语法? (是的,我明白发生了什么……我只是说它对用户来说并不“统一”,不管是否有解释。)
  • @MarkRansom:嗯,这是语言的一个怪癖,因为std::array&lt;int&gt; y = {1,2,3,4}; 使用来自 Clang suggesting 大括号的 warning,而不是关于不允许“在使用直接列表初始化时省略子对象初始化周围的大括号”的硬错误。
  • @Xeo:实际上,在聚合初始化中允许大括号省略,但(显然)在使用直接列表初始化语法时不允许。
【解决方案2】:

因为std::vector 提供了一个接受std::initializer_list&lt;T&gt; 的构造函数,而std::array 没有构造函数,而{1, 2, 3, 4} 大括号初始化列表实际上并未解释为std::initializer_list,而是为std::array 的内部 C 样式数组(这就是第二组大括号的来源:一个用于 std::array,一个用于内部 C 样式成员数组)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-31
    • 2015-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-24
    相关资源
    最近更新 更多