c++ 如果一个析构函数被删除了,编译器还会隐式地生成一个默认构造函数吗?

mlnl4t2r  于 2024-01-09  发布在  其他
关注(0)|答案(1)|浏览(149)

如果删除了析构函数,编译器是否仍隐式生成默认构造函数?
下面的代码可以通过GCC编译:

  1. struct A
  2. {
  3. ~A() = delete;
  4. int x;
  5. int y;
  6. virtual void foo()
  7. {
  8. }
  9. };
  10. int main()
  11. {
  12. A *pmc = new A; // Allowed by the compiler GCC, but causes memory leak
  13. return 0;
  14. }

字符串
这表明GCC认为它可以在这种情况下隐式生成一个默认构造函数。默认构造函数的汇编代码也可以在Godbolt上查看:

  1. A::A() [base object constructor]:
  2. push rbp
  3. mov rbp, rsp
  4. mov QWORD PTR [rbp-8], rdi
  5. mov edx, OFFSET FLAT:vtable for A+16
  6. mov rax, QWORD PTR [rbp-8]
  7. mov QWORD PTR [rax], rdx
  8. nop
  9. pop rbp
  10. ret


然而,当用类型特征进行检验时,答案是否定的:

  1. cout << is_default_constructible<A>::value; // false


那么,is_default_constructible是否代表了C++标准的态度呢?也就是说,在语言标准层面,不允许生成缺省构造函数,但在编译器实现层面,允许生成缺省构造函数。
是这样吗?

sbtkgmzw

sbtkgmzw1#

是的(对于标题中的问题),如果没有其他构造函数是用户声明的,则默认构造函数总是隐式声明的,尽管如果子对象不能被默认初始化或析构,则可以将其定义为删除。类本身的析构函数无关紧要:
如果类X没有用户声明的构造函数,则没有参数的非显式构造函数将隐式声明为默认值(dcl.fct.def(https://eel.is/c++draft/dcl.fct.def))。

  • [class.default.ctor] p1
    std::is_default_constructible<A>失败,因为std::is_(*_)constructible trait并不 * 只 * 检查对象是否可以构造,而是检查直接初始化中具有相应类型的变量的定义是否是良构的,即这里是否
  1. A a();

字符串
将是格式良好的,除非声明不被解释为函数声明。这样的变量定义只有在析构函数也可用时才是格式良好的。
也就是说,在语言标准级别,不允许生成默认构造函数,但在编译器实现级别,允许生成默认构造函数,这是正确的吗?
不,这个问题开始就没有任何意义。如果标准规定构造函数不是隐式声明/定义的,那么符合标准的编译器就不可能以另一种方式来做。

相关问题