隐式定义类的析构函数

Destructor of a class implicitly defined

本文关键字:析构函数 定义      更新时间:2023-10-16

考虑开发人员没有显式声明destructorconstructor的类的情况。我理解在这种情况下,一个班级的destructor将是implicitly declared。那么,只有当类的对象即将被销毁时,destructor才是implicitly defined,这是真的吗?

是构造函数的行为也与上面相同。它是implicitly defined仅当类的对象被创建?

编辑

class A {
  public:
};
int main() {
}

在上面的代码中,~A()将隐式声明。我的问题是,只有当类的对象像

那样实例化时,析构函数的定义才会隐式地进行,这是否正确?
class A {
      public:
    };
    int main() {
      A a;
    }

或者它是隐式定义的,即使对象实例化没有完成

是的,隐式声明的默认构造函数和析构函数是在用于创建或销毁对象实例时隐式定义的。用标准c++ 11的话说:

12.1/6:默认构造函数是默认的,但没有定义为deleted,当它被odr使用时,它被隐式定义(3.2)创建其类类型(1.8)的对象,或者在第一次声明后显式默认该对象。

12.4/5:默认的且未定义为deleted的析构函数在被odr(3.2)使用时被隐式定义销毁其类类型(3.7)的对象,或者在其第一次声明后显式默认的对象。

所以它们是在第二个代码片段中定义的,它创建和销毁A类型的对象,但不是在第一个代码片段中定义的,因为它没有。

一方面,通常不可能决定一个对象是否在任何重要的程序中被创建/销毁,另一方面,只要可观察的行为保持不变,这并不重要。

然而,在defined when object created/destroyeddefined if needed之间有一条细线。在下面的示例中,需要定义Foo::Foo(),因为有可能需要它。但是,您要问在创建对象时是否定义了它,而后者是不可确定的。


*:

class Foo {};
int main(int argc, char *argv[]) {
    if (argc>1) Foo(); // <- impossible to decide if ever constructed/destroyed
}
// On the other hand, compiler might be smart enough to observe that
// Foo does not have any visible behaviour, remove Foo entirely, and in
// effect spit out this:
int main() {}

函数是否定义不是在运行时确定的,因此析构函数不能"定义,只有当对象[…]是关于被销毁"仅仅因为你的可执行文件是静态的,而不是为特定的运行创建的。

但是,如果最终可执行文件中不存在对析构函数的调用,链接器可能选择完全删除该函数。


对于最后一点,考虑以下示例:

class A {
  A() {}
  ~A() {}
};
class B {
  A a; // cannot access dtor nor ctor of A
};

如果你从来没有实例化B,这实际上会编译和链接,因为没有B::B()B::~B()被合成。然而,如果你试图创建一个B的对象,编译器会叫你一些色彩缤纷的名字,仅仅是因为你强迫它合成B::B()B::~B(),这是它不能做的。