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

编译器生成的默认构造函数具有constexpr混淆行为

牛迪
2023-03-14

样本1

template <typename T>
struct A
{

    constexpr A() = default;
    T x;
};

int main(){
    static_assert(A<int>{}.x == int{}, "FAILED");
}

样本2

struct A
{
    constexpr A() = default;
    int x;
};

int main(){
    static_assert(A{}.x == int{}, "Not Equal");
}

我对第一个示例如何编译和传递静态断言感到困惑,而第二个示例未能按照constexpr defaulted default constructor中提到的编译,错误为:默认构造函数的默认定义不是constexpr

尝试阅读以下内容,但无法理解第一个是如何工作的,另一个是如何工作的。http://eel.is/c草案/类别。ctor#类。违约ctor-4

默认的构造函数是默认的,并且没有被定义为删除,当它被odr使用([basic.def.odr])来创建其类类型的对象([intro.object])时,当它需要常量求值([expr.const]),或者当它在第一次声明后显式默认时。隐式定义的默认构造函数执行类的初始化集,该初始化集将由用户为该类编写的默认构造函数执行,该类没有ctor初始化器和空复合语句。如果用户编写的默认构造函数格式错误,则程序格式错误。如果用户编写的默认构造函数将满足Constexr构造函数([dcl.constexpr])的要求,则隐式定义的默认构造函数是Constexr。在隐式定义类的默认构造函数之前,隐式定义其基类及其非静态数据成员的所有非用户提供的默认构造函数。[注意:隐式声明的默认构造函数具有异常规范([except.spec])。显式默认定义可能具有隐式异常规范,请参见[dcl.fct.def]。

非常感谢。

共有1个答案

乐正镜
2023-03-14

以下几点可以说明这个问题:

int main(){
    constexpr A<int> a;
}

试图调用constexpr构造函数会产生此错误(gcc):

<source>: In function 'int main()':
<source>:12:22: error: uninitialized 'const a' [-fpermissive]
   12 |     constexpr A<int> a;
      |                      ^
<source>:4:8: note: 'const struct A<int>' has no user-provided default constructor
    4 | struct A
      |        ^
<source>:7:15: note: constructor is not user-provided because it is explicitly defaulted in the class body
    7 |     constexpr A() = default;
      |               ^
<source>:8:7: note: and the implicitly-defined constructor does not initialize 'int A<int>::x'
    8 |     T x;
      |       ^

但是,如果我没有遗漏什么,那么constexpr构造函数应该已经是一个错误,因为它不能是constexpr(请参见此处)。

gcc和clang都接受您的代码,但都产生了一个错误,试图调用Constexpr构造函数。我想这是一个编译器错误。

 类似资料:
  • 问题内容: 当我写课时 编译器生成的构造函数是 public 还是 default ? 公众会喜欢 而默认类似于 问题答案: 这取决于您的 类可见性* 。编译器使用类可见性并生成具有 相同可见性 的无参数默认构造函数 *

  • 问题内容: 以下是两种方法: 具有所有类属性的构造函数 优点:我必须输入确切数量的参数类型,所以如果出现错误,编译器会警告我(顺便说一句,有什么方法可以防止错误地在参数列表中切换两个Integer的问题?) 缺点:如果我有很多属性,则实例化行可能会变得很长,并且可能跨越两行或更多行 setter和默认的空构造函数 优点:我可以清楚地看到自己的设置,因此,如果我做错了什么,我可以在键入时立即查明它(

  • 以下代码使用Clang(3.9.1测试)和GCC(6.3测试)编译,如此链接所示:https://godbolt.org/g/kO1nBa.但是,MSVC(19.00.24215.1测试)无法编译它: 错误C2131:表达式未计算为常量 注意:失败是由赋值操作的计算引起的 注意:在评估'ExtraResidentsValueWitnessTable::ExtraResidentsValueWitn

  • 问题内容: 默认构造函数到底是什么?你能告诉我以下哪个是默认构造函数,它与其他构造函数有何不同? 问题答案: 他们都不是。如果定义,则不是默认值。 除非你定义另一个构造函数,否则默认构造函数是自动生成的无参数构造函数。任何未初始化的字段都将设置为其默认值。对于你的榜样,它看起来像这样假设的类型String,int以及int,那类本身是公共的: 这与 完全没有构造函数。但是,如果定义至少一个构造函数

  • 问题内容: 我知道我在这里问一些严重的101问题… 我有一些课,还有一个延伸课。在我有一个构造函数,它接受一组参数,并对其字段进行设置。派生类(例如)通常不需要进行修改。现在我的IDE给我 “ Foo中没有默认的构造函数” 。从一点点谷歌搜索,这似乎是因为“构造函数没有继承”。因此,一切都很好,但是我现在如何使它工作而不在每个派生类中复制此构造函数?我假设有一个更合理的方法? 问题答案: 使用构造

  • 问题内容: 我不想为我的班级创建默认的构造函数。 但是Spring似乎坚持: 这真的有必要吗? 问题答案: 你是如何定义bean的?听起来你可能已经告诉Spring实例化你的bean,例如以下之一: 没有提供构造函数参数的地方。前一个将使用默认(或不使用arg)构造函数。如果要使用接受参数的构造函数,则需要使用如下元素来指定它们: 如果你想在你的应用程序上下文引用另一个bean中,你可以使用它做的