【问题标题】:Default Initializer of empty struct in clang vs gccclang vs gcc中空结构的默认初始化器
【发布时间】:2017-02-15 13:46:25
【问题描述】:

以下代码使用 GCC 的某些版本和 Clang 的某些版本进行编译(请参阅下面的哪些版本)。

struct my_struct {};

int main(int argc, char** argv) {
  const my_struct my_object;
  return 0;
};

使用 :g++ clang_error.cppclang++ clang_error.cpp 编译。我在 4.8.4 有 g++,在 3.6.0 有 clang++。

错误信息是:

clang_error.cpp:7:19: error: default initialization of an object of const type 'const my_struct' without a user-provided default constructor
   const my_struct my_object;
                   ^
clang_error.cpp:7:28: note: add an explicit initializer to initialize 'my_object'
   const my_struct my_object;
                            ^
                             = {}
1 error generated.

受影响的版本

使用 Compiler Explorer here,我可以看到最高 4.5.4 的 GCC 受到影响。 Clang 在 3.9.0 之前受到影响。

问题

我的问题是:C++ 标准对此有何评论? 理想情况下,我会关心 C++14,但我对此并不挑剔。

上面的示例代码符合标准吗?

到目前为止我发现了什么

我在 C++14 的 Draft N3797 中发现了以下内容。

§ 7.1.6.1 cv 限定符 [dcl.type.cv]
2 [ 注意:声明一个变量 const 会影响它的链接(7.1.1)和它在常量表达式中的可用性(5.19)。 如 8.5 所述,const 限定类型的对象或子对象的定义必须指定一个初始化器 或接受默认初始化。 — 结束注释]

§ 8.5
7 默认初始化 T 类型的对象意味着:
— 如果 T 是(可能是 cv 限定的)类类型(第 9 条),则调用 T 的默认构造函数(12.1)(并且 如果 T 没有默认构造函数,则初始化格式错误或重载决议 (13.3) 导致 歧义或在初始化上下文中删除或无法访问的函数中);
— 如果 T 是数组类型,则每个元素都是默认初始化的;
— 否则,不执行初始化。

【问题讨论】:

  • 请推荐更好的标签。
  • 看起来像 this 解释它。
  • 那么新版本的 GCC 和 Clang 在标准方面被破坏了?当然,标准中必须有一条规则允许这些编译器的当前行为。您的链接答案虽然有用,但没有回答我这个问题。
  • This 可能是答案。它链接到 C++11 标准委员会的 this 问题。现在,只需要一个链接到该标准的决议。
  • 你是对的,这是核心问题 253。GCC 在gcc.gnu.org/gcc-4.6/changes.html#cplusplus记录了它对 gcc 4.6 的行为变化@

标签: c++ g++ c++14 clang++


【解决方案1】:

C++ 标准对此有何规定?

上面的示例代码符合标准吗?

在 C++14 中,它是不一致的:

n4431 (2015) 标准草案 [dcl.init] / 7:

如果程序要求对 const 限定类型的对象进行默认初始化 吨 , 吨 应该是一个类类型 使用用户提供的默认构造函数。

my_struct 没有用户提供的默认构造函数,所以你不应该默认初始化。

但是,一些较新的编译器似乎选择放宽该规则,可能是因为它受到缺陷报告的影响:DR 253


即将出台的标准改变了措辞:

当前(2017)标准草案[dcl.init] / 7

如果 T 的默认初始化会调用 T 的用户提供的构造函数(不是从基类继承)或如果

,则类类型 T 是 const-default-constructible

(7.4) T 的每个直接非变体非静态数据成员 M 都有一个默认成员初始化器,或者,如果 M 是类类型 X(或其数组),则 X 是 const-default-constructible,

(7.5) 如果 T 是具有至少一个非静态数据成员的联合,则恰好一个变体成员具有默认成员初始值设定项,

(7.6) 如果 T 不是联合,对于每个具有至少一个非静态数据成员(如果有)的匿名联合成员,恰好一个非静态数据成员具有默认成员初始化器,并且

(7.7) 每个可能构造的 T 基类都是 const-default-constructible。

如果程序要求对 const 限定类型 T 的对象进行默认初始化,则 T 应为 const-default-constructible 类类型或其数组。

措辞对我来说有点模棱两可,但我认为由于my_struct 没有违反 7.4 的成员(并且不是工会,所以 7.5 不适用,没有工会成员,所以 7.6 不适用,也没有基础,因此 7.7 不适用),它是 const-default-constructible,因此示例将是一致的。

【讨论】:

    猜你喜欢
    • 2013-08-21
    • 2017-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-29
    相关资源
    最近更新 更多