简体   繁体   English

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

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

When I compile the following piece of code with CLANG:当我用 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;
}

by issuing the command:通过发出命令:

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

It issues the warning:它发出警告:

warning: suggest braces around initialization of subobject [-Wmissing-braces]警告:建议围绕子对象的初始化使用大括号 [-Wmissing-braces]

CLANG DEMO叮当演示

However, GCC compiles this program with out issuing a warning at all.然而,GCC 编译这个程序时根本没有发出警告。

GCC DEMO海湾合作委员会演示

Q:问:

  1. Which compiler is right?哪个编译器是对的?
  2. What's the reason that Clangs warns me? Clangs 警告我的原因是什么?

In some cases, braces can be elided.在某些情况下,可以省略大括号。 This is one of those cases.这是其中一种情况。 The outer-most braces for initializing a and b are optional.用于初始化ab的最外面的大括号是可选的。 It is syntactically correct either way - but it's clearer to just include them.无论哪种方式,它在语法上都是正确的 - 但只包含它们会更清楚。 Clang is just warning you (warning, not error) about this - it's a perfectly valid warning. Clang 只是就此警告您(警告,而不是错误)——这是一个完全有效的警告。 And as chris , points out, with -Wmissing-braces , gcc issues the same warning.正如chris指出的那样,使用-Wmissing-braces ,gcc 会发出相同的警告。 Ultimately, both compilers accept the code, which is correct;最终,两个编译器都接受了正确的代码; it is, after all, a valid program.毕竟,它是一个有效的程序。 That's all that matters.这才是最重要的。

From [dcl.init.aggr]:来自 [dcl.init.aggr]:

Braces can be elided in an initializer-list as follows.大括号可以在初始化列表中省略,如下所示。 If the initializer-list begins with a left brace, then the succeeding comma-separated list of initializer-clauses initializes the members of a subaggregate;如果初始值设定项列表以左大括号开头,则后续的以逗号分隔初始值设定项列表将初始化子聚合的成员; it is erroneous for there to be more initializer-clauses than members.初始化器子句比成员多是错误的。 If, however, the initializer-list for a subaggregate does not begin with a left brace, then only enough initializer-clauses from the list are taken to initialize the members of the subaggregate;然而,如果子聚合的初始化器列表不以左大括号开头,则仅从列表中获取足够的初始化器子句来初始化子聚合的成员; any remaining initializer-clauses are left to initialize the next member of the aggregate of which the current subaggregate is a member.留下任何剩余的初始化子句来初始化当前子聚合是其成员的聚合的下一个成员。 [ Example: [ 例子:

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

is a completely-braced initialization: 1 , 3 , and 5 initialize the first row of the array y[0] , namely y[0][0] , y[0][1] , and y[0][2] .是完全支撑的初始化: 135初始化数组y[0]的第一行,即y[0][0]y[0][1]y[0][2] . Likewise the next two lines initialize y[1] and y[2] .同样,接下来的两行初始化y[1]y[2] The initializer ends early and therefore y[3] s elements are initialized as if explicitly initialized with an expression of the form float() , that is, are initialized with 0.0 .初始化器提前结束,因此y[3]的元素被初始化,就好像用float()形式的表达式显式初始化一样,即用0.0初始化。 In the following example, braces in the initializer-list are elided;在以下示例中,省略了初始化列表中的大括号; however the initializer-list has the same effect as the completely-braced initializer-list of the above example,然而,初始化列表与上面例子中的完全支撑初始化列表具有相同的效果,

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

The initializer for y begins with a left brace, but the one for y[0] does not, therefore three elements from the list are used. y的初始值设定项以左大括号开头,但y[0]的初始值设定项没有,因此使用了列表中的三个元素。 Likewise the next three are taken successively for y[1] and y[2] .同样,对于y[1]y[2]连续采用接下来的三个。 —end example ] —结束示例]

Which compiler is right?哪个编译器是对的?

Both compilers are right.两个编译器都是对的。 Brace-elision is a feature that allows an aggregate to be initialized by a single pair of braces. Brace-elision是一个特性,它允许一个聚合被一对大括号初始化。 Each member suboject is initialized with as many initializer-clauses as necessary.每个成员子对象都根据需要使用尽可能多的初始化子句进行初始化 This is to allow a more convenient form of initialization.这是为了允许更方便的初始化形式。

What's the reason that Clangs warns me? Clangs 警告我的原因是什么?

Clang is being helpful by warning you because while you are able to elide the braces, it isn't always clear how the aggregate will be initialized if you aren't careful. Clang 警告你很有帮助,因为虽然你可以省略大括号,但如果你不小心,聚合将如何初始化并不总是很清楚。 You have to be certain which initializer-clauses pertain to which member subobjects.您必须确定哪些初始值设定项子句属于哪些成员子对象。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM