当前位置: 首页 > 知识库问答 >
问题:

为什么gcc允许没有用户声明的默认构造函数的const对象,但不允许clang?

宣意致
2023-03-14

最近为什么const对象需要用户提供的默认构造函数?被标记为为什么C需要用户提供的默认构造函数来默认构造const对象?。我正在使用coliru和rextexter来测试各种版本的gcc(g-4.7、g-4.8、g-4.9)和clang(3.4和3.5),以查看此行为是否在较新版本的编译器中引入。这里我们有两个测试用例,分别来自两个问题:

class A {
public:
    void f() {}

};

int main()
{
    A a;       // OK
    const A b; // ERROR

    a.f();
    return 0;
}

和:

struct B{
  B():x(42){}
  int doSomeStuff() const{return x;}
  int x;
};

struct A{
  A(){}//other than "because the standard says so", why is this line required?

  B b;//not required for this example, just to illustrate
      //how this situation isn't totally useless
};

int main(){
  const A a;
}

叮当出错:

 error: default initialization of an object of const type 'const A' requires a user-provided default constructor
  A const a;
          ^

预期但不是gcc,也不是MSVC。我想我可能会疯掉,因为标准引述清楚地表明:

§ 8.5

6默认初始化T类型的对象意味着:

-如果T是(可能是cv限定的)类类型(第9条),则调用T的默认构造函数(如果T没有可访问的默认构造函数,则初始化格式错误);

[...]

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

11如果没有为对象指定初始值设定项,则默认初始化该对象;[...]

第二个问题中的非POD语言似乎在n3337中缺失,所以我可能遗漏了一些可能已经改变的东西。这是一个错误、重复还是我遗漏了什么?

共有1个答案

萧胜
2023-03-14

该规范目前需要用户提供的默认构造函数,但似乎GCC正在实现基于DR 253的更改,该更改表示如果所有子对象都将在没有用户提供的默认构造函数的情况下初始化,那么用户提供的默认构造函数是不需要的。

此更改只是草案状态,尚未被接受,也不是标准的一部分。所以我认为这是GCC开发人员的行为,但我不确定这是否是符合标准的扩展。

下面是对第一个示例的更改,该更改导致GCC产生错误:

class A {
public:
    void f() {}

    int i;
};

int main()
{
    A a;       // OK
    const A b; // ERROR

    a.f();
    return 0;
}

请注意,gcc将错误降级为带有-fpermissive标志的警告。

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=42844

 类似资料:
  • Perl有一个未定义函数的概念。已声明但未定义的函数。 这个函数现在存在于符号表中,它可以用来解析方法调用。但是为什么这个“特征”会存在呢?在C语言中,这是因为函数是类型检查的,有时您希望在定义之前进行调用(例如解决循环依赖关系)。但是Perl没有这样的特性,所有的函数符号都是在运行时而不是编译时解析的。 > 如果不是原型,为什么它会存在? 为什么在方法解析中使用未定义的子程序?为什么不完全忽略它

  • 我们举个例子: 一个常见的解决方案是转移到一个抽象类,但是在我的具体案例中,我有一个枚举的接口,所以在这里不适用。我想这不是被忽略了,就是因为接口背后的原始想法,即它们是可用方法的“契约”,但我想我需要关于这是怎么回事的输入。 我读过“为什么Java 8接口方法中不允许使用”final“?”,其中说: 默认方法的基本思想是:它是具有默认实现的接口方法,派生类可以提供更具体的实现 与关联问题一样,由

  • 问题内容: 我在日食中收到很多这样的警告: 变量“ myVariable”必须是私有的,并且具有访问器方法。 我想得到它们是因为我没有在eclipse中手动将protectedAllowed设置为true。但是为什么默认情况下将其设置为false?我不应该使用受保护的属性吗? 问题答案: 从理论上讲,受保护的属性(变量)在面向对象的语言中是一种反模式。如果仅子类需要访问其超类的成员属性,则将属性本

  • 问题内容: 我想知道Java中是否有特殊原因总是使用“ ”而不是“ ”来定义类型参数的界限。 例: 被禁止但是 是正确的。是什么原因呢? 问题答案: 在类“实现”还是“扩展”之间,通用约束语言没有语义差异。约束可能性是“扩展”和“超级”-也就是说,该类是可分配给其他类的对象(扩展),还是该类可从该类分配(超级)。

  • 问题内容: 我刚接触PHP,但是多年来我一直在使用类似的语言进行编程。我被以下内容弄糊涂了: 它产生了语法错误:这就是调用。 但这很好用: 碰了一会儿之后,我被告知您不能在默认属性中调用函数。你必须在做。我的问题是:为什么?这是“功能”还是草率的实现?有什么根据? 问题答案: 编译器代码建议这是设计使然,尽管我不知道其背后的官方原因是什么。我也不确定要可靠地实现此功能需要花费多少精力,但是目前完成

  • 我想知道为什么这个程序不编译(在msvc,gcc和clang上的行为相同): 根据我的预期,删除的复制构造函数应该让其他ActionDecorator实例构造ActionDecorator,因为它是多态类型的操作。相反,我必须显式地将ActionDecorator实例转换为Action