【问题标题】:C++11: Correct std::array initialization?C++11:正确的 std::array 初始化?
【发布时间】:2012-12-20 03:19:14
【问题描述】:

如果我按如下方式初始化 std::array,编译器会给我一个关于缺少大括号的警告

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

这解决了问题:

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

这是警告信息:

missing braces around initializer for 'std::array<int, 4u>::value_type [4] {aka int [4]}' [-Wmissing-braces]

这只是我的 gcc 版本中的一个错误,还是故意这样做的?如果有,为什么?

【问题讨论】:

  • std::array 是一个聚合。不过,我认为他们可能会在未来使用一套。
  • @chris 究竟是什么意思?
  • 好吧,您知道如何拥有struct S {int i; int j;}; 并使用S s = {5, 6}; 对其进行初始化吗?那是聚合初始化。 std::array 包含一个内置数组,可以通过初始化列表进行初始化,这就是内部集合。外部集用于聚合初始化。
  • @chris 所以在我的例子中 "{1, 2, 3, 4}" 只是一个 std::initializer_list 对象,它本身必须放在实际的初始化大括号中?
  • 好吧,我不太确定在引入该类型后如何处理内置数组初始值设定项列表,但这就是要点,是的。一个用于类,另一个用于类内的数组。

标签: c++ arrays c++11 initialization c++14


【解决方案1】:

这是std::array的裸实现:

template<typename T, std::size_t N>
struct array {
    T __array_impl[N];
};

它是一个聚合结构,其唯一数据成员是传统数组,因此内部{}用于初始化内部数组。

在聚合初始化的某些情况下允许大括号省略(但通常不推荐),因此在这种情况下只能使用一个大括号。见这里:C++ vector of arrays

【讨论】:

  • 所有版本的标准都允许大括号省略。
  • 嗯,愚蠢的 GCC 警告 >.> 我不知道已经是这种情况了。
  • 我遇到了同样的问题(到现在 2016 年),但我用以下语法修复了它:'std::array a[] = {1,2,3,4} ;'所以我添加了方括号而不是嵌套的花括号。也许有人知道为什么这个变种对我有用?
  • @Sam 这有不同的含义。您发布的语法是创建一个 std::arrays 数组(二维数组),而不是单个数组(一维)。
【解决方案2】:

根据cppreference。仅当省略 = 时才需要双括号。

// construction uses aggregate initialization
std::array<int, 3> a1{ {1,2,3} };    // double-braces required
std::array<int, 3> a2 = {1, 2, 3}; // except after =
std::array<std::string, 2> a3 = { {std::string("a"), "b"} };

【讨论】:

  • @cyberpunk_ 仅当您的编译器实现了 DR #1270 以解除该限制。
  • @Chubbi 但是为什么它会给我一个警告“std::array a = {1, 2, 3, 4}”呢?
  • @cyberpunk_ 这只是一个虚假的警告。
  • @cyberpunk_ 你可以用额外的大括号轻松满足它。这不是 GCC 唯一令人讨厌的警告(见过suggest parentheses around ‘&amp;&amp;’ within ‘||’?)
  • 警告意味着编译器作者认为您可能不够聪明,无法正确使用该语言功能。
【解决方案3】:

C++17std::array类模板参数推导(CTAD)

这个new C++17 featureused by the standard library,现在允许我们省略模板类型,以便以下工作:

main.cpp

#include <array>

int main() {
    std::array a{1, 2, 3};
}

而不是std::array&lt;int, 3&gt; a{1, 2, 3};

测试:

g++ -ggdb3 -O0 -std=c++17 -Wall -Wextra -pedantic -o main.out main.cpp

例如,如果我们设置-std=c++14,则编译失败:

error: missing template arguments before ‘a’

另见:Deduce std::array size?

在 Ubuntu 18.04、GCC 7.5.0 上测试。

【讨论】:

    【解决方案4】:

    CWG 1270 之前的 C++11 中需要双括号(修订后的 C++11 和 C++14 及更高版本中不需要):

    // construction uses aggregate initialization
    std::array<int, 3> a1{ {1, 2, 3} }; // double-braces required in C++11 prior to the CWG 1270 revision
                                        // (not needed in C++11 after the revision and in C++14 and beyond)
    std::array<int, 3> a2 = {1, 2, 3};  // never required after =
    

    std::array reference

    【讨论】:

      猜你喜欢
      • 2014-04-26
      • 2012-03-08
      • 2020-12-23
      • 1970-01-01
      • 1970-01-01
      • 2016-02-08
      相关资源
      最近更新 更多