首页 文章

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

提问于
浏览
2

当我用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

它发出警告:

警告:建议围绕子对象初始化[-Wmissing-braces]

CLANG DEMO

但是,海湾合作委员会编制了这个程序而没有发出警告 .

GCC DEMO

问:

  • 哪个编译器是对的?

  • Clangs警告我的原因是什么?

2 回答

  • 2

    在某些情况下,可以省略牙箍 . 这是其中一个案例 . 用于初始化 ab 的最外侧大括号是可选的 . 它在语法上都是正确的 - 但它是一个非常有效的警告.1166410_是一个非常有效的警告 . 并且chris指出,使用 -Wmissing-braces ,gcc会发出相同的警告 . 最终,两个编译器都接受了正确的代码;毕竟,这是一个有效的计划 . 这一切都很重要 .

    来自[dcl.init.aggr]:

    可以在初始化列表中省略大括号,如下所示 . 如果初始化列表以左括号开头,则后续的逗号分隔的initializer-clause列表初始化子集合的成员;如果有比成员更多的初始化子条款是错误的 . 但是,如果子聚合的初始化列表不以左括号开头,则只从列表中获取足够的初始化子句来初始化子聚合的成员;剩下的任何初始化子句用于初始化当前子聚合为成员的聚合的下一个成员 . [例子:float y [4] [3] = {
    {1,3,5},
    {2,4,6},
    {3,5,7},
    };
    是一个完全支撑的初始化:1,3和5初始化数组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] . - 末端的例子]

  • 0

    哪个编译器是对的?

    两个编译器都是对的 . Brace-elision是一种允许聚合由一对大括号初始化的功能 . 每个成员子项目都根据需要初始化为尽可能多的初始化子句 . 这是为了允许更方便的初始化形式 .

    Clangs警告我的原因是什么?

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

相关问题