当我聚合初始化数组而 gcc 没有时,Clang 警告我

Clang warns me when I aggregate initialize an array while gcc doesn't

本文关键字:Clang 警告 初始化 数组 gcc      更新时间:2023-10-16

当我用CLANG编译以下代码时:

#include <iostream>
#include <array>
#include <algorithm>
#include <functional>
int main() {
  std::array<int, 2> a = {1, 2};
  std::array<int, 2> b = {2, 1};
  std::array<int, 2> c;
  std::transform(a.begin(), a.end(), b.begin(), c.begin(), std::multiplies<int>());
  for(auto &&i : c) std::cout << i << " ";
  std::cout << std::endl;
}

通过发出命令:

clang++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp

它发出警告:

警告:建议在子对象初始化周围使用大括号 [-缺少大括号]

叮当演示

但是,GCC编译此程序时根本没有发出警告。

海湾合作委员会演示

问:

  1. 哪个编译器是正确的?
  2. 叮当当警告我的原因是什么?

在某些情况下,可以省略大括号。这是其中一种情况。用于初始化ab的最外大括号是可选的。无论哪种方式,它在语法上都是正确的 - 但只包含它们更清楚。Clang只是警告你(警告,而不是错误(- 这是一个完全有效的警告。正如克里斯指出的那样,-Wmissing-braces,gcc发出了同样的警告。最终,两个编译器都接受代码,这是正确的;毕竟,这是一个有效的程序。这才是最重要的。

来自 [dcl.init.aggr]:

可以在初始值设定项列表中省略大括号,如下所示。如果初始值设定项列表以左大括号开头,则 后面的逗号分隔初始值设定项子句列表初始化子聚合的成员;是的 错误的初始值设定项子句多于成员。但是,如果子聚合的初始值设定项列表 不以左大括号开头,则仅从列表中获取足够的初始值设定项子句 初始化子聚合的成员;任何剩余的初始值设定项子句都留给初始化下一个 当前子聚合是其成员的聚合的成员。[ 示例:

float y[4][3] = {
    { 1, 3, 5 },
    { 2, 4, 6 },
    { 3, 5, 7 },
};

是一个完全支撑的初始化:135初始化数组y[0]的第一行,即y[0][0]y[0][1]y[0][2]。同样,接下来的两行初始化 y[1]y[2] 。初始值设定项提前结束,并且 因此y[3] s 元素被初始化,就像使用形式为 float() 的表达式显式初始化一样, 也就是说,用0.0初始化。在下面的示例中,省略了初始值设定项列表中的大括号;然而 初始值设定项列表与上述示例中的完全支撑的初始值设定项列表具有相同的效果,

float y[4][3] = {
    1, 3, 5, 2, 4, 6, 3, 5, 7
};
y 的初始值设定项以

左大括号开头,但 y[0] 的初始值设定项不以左大括号开头,因此三个元素来自 使用列表。同样,接下来的三个依次用于y[1]y[2]—结束示例 ]

哪个编译器是正确的?

两个编译器都是正确的。大括号消除是一种允许聚合由一对大括号初始化的功能。每个成员 suboject 都根据需要使用任意数量的初始值设定项子句进行初始化。这是为了允许更方便的初始化形式。

叮当当警告我的原因是什么?

Clang通过警告你很有帮助,因为虽然你能够省略大括号,但如果你不小心,并不总是清楚聚合将如何初始化。您必须确定哪些初始值设定项子句与哪些成员子对象有关。