我真的需要为 const 对象实现用户提供的构造函数吗?

我有代码:

class A {上市:A() = 默认值;私人的:国际我= 1;};int main() {常量 A;返回0;}

它在 g++ 上编译得很好(参见 ideone),但在 clang++ 上失败并出现错误:

<块引用>

const 类型const A"对象的默认初始化需要用户提供的默认构造函数

我在 LLVM bug-tracker 上报告了这个问题并得到了它无效.

我认为试图说服 clang 开发人员毫无意义.另一方面,我没有看到这种限制的原因.

<小时>

任何人都可以建议,如果 C++11 标准以某种方式暗示此代码无效?或者我应该向 g++ 报告一个错误?或者也许语言规则有足够的自由度以多种方式处理这些代码?

解决方案

N3797 §8.5/7 说:

<块引用>

如果程序要求对具有 const 限定类型 T 的对象进行默认初始化,则 T 应是具有用户提供的默认构造函数的类类型.

对此没有进一步的示例或解释.我同意这看起来很奇怪.此外,当类类型需要用户声明构造函数时,该规则在 C++11 中更新为比在 C++03 中更严格.(您的构造函数是用户声明的.)

解决方法是使用 {} 请求初始化值,或者使用 Dietmar 巧妙的类外 inline 定义.

如果您添加另一个没有初始化程序的成员,GCC 确实提供了诊断(而且相当不错,参考了较新的 C++11 要求).

 私有:国际我= 1;国际 j;

unmem.cpp:11:11: 错误:未初始化的 const ‘a’ [-fpermissive]常量 A;^unmem.cpp:1:7: 注意:'const class A' 没有用户提供的默认构造函数A类{^unmem.cpp:3:5:注意:构造函数不是用户提供的,因为它在类主体中被明确默认A() = 默认值;^unmem.cpp:7:9: 注意:隐式定义的构造函数不初始化‘int A::j’国际 j;

海湾合作委员会 来源指的是DR 253a>, 为什么必须初始化空的或完全初始化的 const 对象? 这是标准中的一个悬而未决的问题,最后更新于 2011 年 8 月(C++11 后),并附有此注释:><块引用>

如果隐式默认构造函数初始化所有子对象,则不需要初始化器.

因此,虽然 Clang 符合 C++11(并将按原样符合 C++14),但 GCC 正在实施标准化委员会的最新想法.

提交了 GCC 错误.我预测您将需要 -pedantic 来获得诊断何时(以及是否)修复了错误.

I have the code:

class A {
  public:
    A() = default;

  private:
    int i = 1;
};

int main() {
  const A a;
  return 0;
}

It compiles fine on g++ (see ideone), but fails on clang++ with error:

default initialization of an object of const type 'const A' requires a user-provided default constructor

I reported this issue on LLVM bug-tracker and got it INVALID.

I see it absolutly pointless to try to convince the clang developers. On the other side, I don't see the reason for such restriction.


Can anyone advise, if the C++11 Standard somehow implies this code to be invalid? Or should I just report a bug to g++? Or maybe there is enough freedom in language rules to handle this code in many ways?

解决方案

N3797 §8.5/7 says:

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.

There's no further example or explanation of this. I agree it seems pretty bizarre. Furthermore the rule was updated in C++11 to be more restrictive than it was in C++03, when class types needed user-declared constructors. (Your constructor is user-declared.)

The workaround is be to ask for value initialization using {}, or use Dietmar's clever out-of-class inline definition.

GCC does provide a diagnosis (and quite a nice one, referring to the newer C++11 requirements) if you add another member without an initializer.

  private:
    int i = 1;
    int j;

?

unmem.cpp:11:11: error: uninitialized const ‘a’ [-fpermissive]
   const A a;
           ^
unmem.cpp:1:7: note: ‘const class A’ has no user-provided default constructor
 class A {
       ^
unmem.cpp:3:5: note: constructor is not user-provided because it is explicitly defaulted in the class body
     A() = default;
     ^
unmem.cpp:7:9: note: and the implicitly-defined constructor does not initialize ‘int A::j’
     int j;

The GCC source refers to DR 253, Why must empty or fully-initialized const objects be initialized? This is an open issue in the standard, last updated in August 2011 (post-C++11) with this note:

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

Therefore whereas Clang complies with C++11 (and will comply as-is with C++14), GCC is implementing the latest thinking of the standardization committee.

Filed a GCC bug. I predict that you'll need -pedantic to get a diagnosis when (and if) the bug is fixed.

相关文章