带大括号的char数组的非静态成员初始化在gcc中给出错误,而在clang中没有

Non-static member initialization of char array with brace gives an error in gcc while not in clang

本文关键字:错误 出错 而在 clang gcc char 数组 初始化 静态成员      更新时间:2023-10-16

考虑以下代码:

#include <iostream>
class A
{
    char name[40] = { "Blank" }; // note the braces here
public:
    const char *getName() { return name; }
};
int main()
{
    A a;
    std::cout << a.getName() << std::endl;
}

给出gcc(最新版本5.2.0)的错误:

prog.cpp:5:28: error: invalid conversion from 'const char*' to 'char' [-fpermissive]
  char name[40] = { "Blank" };
                            ^

clang的情况不是这样,它与-std=c++11 -pedantic -Wall完美地编译。

在这里用大括号表示非静态初始化项真的不正确吗?

问题:是否有大括号并不重要。例如,数组的定义,如:

char text[] = "some text";

等价于:

char text[] = { "some text" };

代码是有效的,并且现在被GCC主干接受。我认为它是由PR 65815修复的,括号省略在NSDMI

中不起作用

这个标准在我看来不是很清楚,但是我想说CLang是对的:

8.5.1说:

§2:当聚合由初始化列表初始化时,如8.5.4所述,初始化列表中的元素按下标递增或成员顺序作为聚合成员的初始化式。这是gcc的解释:name是一个数组,有一个大括号初始化列表,所以数组的第一个元素(一个char)用char数组初始化=> error

但是8.5.2明确地说:一个窄字符类型的数组…可以用窄字符串字面值初始化…或用大括号括起来的适当类型的字符串(强调我的)

我的解释是,标准认为字符数组足够特殊,即使它违反了8.5.1§2

,也可以显式地允许用大括号括起来的字符串文本有效。

来自c++标准工作草案n4527 [dcl.init]。初始化可以这样写:

初始化

initializer:
  brace-or-equal-initializer
  ( expression-list )
brace-or-equal-initializer:
  = initializer-clause
  braced-init-list
initializer-clause:
  assignment-expression
  braced-init-list
initializer-list:
  initializer-clause...opt
  initializer-list,initializer-clause...opt
braced-init-list:
  {initializer-list,opt}
  { }

类成员声明

member-declarator:
  declarator virt-specifier-seq opt pure-specifier opt
  declarator brace-or-equal-initializer opt

从我读到的,似乎gcc不符合标准。因为使用大括号的类成员初始化被标准接受。

fwiw, g++在基于括号的初始化和/或构造函数调用方面有几个问题,包括最近报告的一些问题。

然而(编辑),正如Jonathan正确指出的那样,大多数(所有?)这些都可以很容易地解决。我已经成功地将旧的括号语法替换为受影响的代码位。

听到这样的情况是有教育意义的,但幸运的是,我个人没有发现这样的情况,所以g++对我来说仍然非常有用(注释解释了为什么我在某些奇怪的地方使用旧语法!)

相关文章: