gpt4 book ai didi

c++ - 常量 T{};作品,常量T;当 T 是非 POD 时失败,

转载 作者:IT老高 更新时间:2023-10-28 13:01:10 27 4
gpt4 key购买 nike

首先,我有一个结构,它有一个值和一个默认值

struct S {
int a = 1;
};

当 gcc 和 clang 都是 non-const/non-constexpr 时,可以默认构造此类型。在两者下,std::is_pod<S>::valuefalse .奇怪的行为如下:

S s1; // works under both
const S s2{}; // works under both
const S s3; // only works in gcc, clang wants a user-provided constructor

以下尝试都不会影响 clang:

struct S {
int a = 1;
constexpr S() = default; // defaulted ctor
virtual void f() { } // virtual function, not an aggregate
private:
int b = 2; // private member, really not an aggregate
};

我唯一能做的就是添加 constexpr S() { }明确地。 const S s; 对我来说似乎真的错了失败,而 const S s{};尤其是当类型不是聚合时。

标准让我觉得Clang是对的
N4296 : 8.5/7

If a program calls for the default initialization of an object of a const-qualified type T, T shall be a class type with a user-provided default constructor

那么为什么 gcc 允许这样做,并且是 S{};不是默认初始化,即使类型不是 POD 或聚合?

最佳答案

const S s3;

被 [dcl.init]/12 覆盖:

If no initializer is specified for an object, the object is default-initialized.

因此,根据您的报价要求,必须存在用户提供的默认构造函数。像这样添加一个

struct S {
int a = 1;
constexpr S(){}
};

然后 makes the declaration compile fine .

[..] especially when the type is not an aggregate.

S 在您的情况下是一个聚合,以及 const S s{} 有效的原因。 const S s{} 应用聚合初始化,一切正常。
如果 S 不是聚合,则

List-initialization of an object or reference of type T is defined as follows:

  • If T is an aggregate, aggregate initialization is performed (8.5.1).
  • Otherwise, if the initializer list has no elements and T is a class type with a default constructor, the object is value-initialized.

现在考虑值初始化的定义:

To value-initialize an object of type T means:

  • if T is a (possibly cv-qualified) class type (Clause 9) with either no default constructor (12.1) or a default constructor that is user-provided or deleted, then the object is default-initialized;
  • if T is a (possibly cv-qualified) class type without a user-provided or deleted default constructor, then the object is zero-initialized and the semantic constraints for default-initialization are checked, and if T has a non-trivial default constructor, the object is default-initialized;

默认 ctor 确实很重要,因为成员有一个初始化程序 ([class.ctor]/4.9),但这无关紧要,因为无论如何都要检查约束。因此它是默认初始化,并且行

const S s{};

一样有效(或无效!)
const S t;

So why does gcc allow this

嗯:

  1. 就目前的标准而言,GCC 是不合规的;见上文。

  2. 有一个活跃的 CWG 问题,#253 ,创建于十五年前,涵盖了类似的场景。 2011 年 session 上关于这个的最后说明说

    If the implicit default constructor initializes all subobjects, no initializer should be required.

    S 的隐式默认构造函数就是这种情况,这将使你的所有行都有效。

  3. GCC 开发者(例如 here)暗示由于委员会基本同意上述决议,GCC 的当前行为是可行的,不应调整。因此,人们很可能会争辩说 GCC 是正确的,并且标准被打破了。

关于c++ - 常量 T{};作品,常量T;当 T 是非 POD 时失败,,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29683381/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com