C++ 为什么在释放分配给某个对象的内存之前调用该对象的默认析构函数?

C++ 为什么在释放分配给某个对象的内存之前调用该对象的默认析构函数?,c++,memory-management,C++,Memory Management,我看到一些代码执行以下操作: ExampleObject< T > * eo = const_cast< ExampleObject< T > * >(this); eo->~ExampleObject(); free( eo ); ExampleObject*eo=const\u cast(此项); eo->~ExampleObject(); 免费(eo); 正在讨论的ExampleObject已使用placement new分配。 没有提供用户定

我看到一些代码执行以下操作:

ExampleObject< T > * eo = const_cast< ExampleObject< T > * >(this);
eo->~ExampleObject();
free( eo );
ExampleObject*eo=const\u cast*>(此项);
eo->~ExampleObject();
免费(eo);
正在讨论的ExampleObject已使用placement new分配。 没有提供用户定义的析构函数,所以我认为这里使用的是编译器提供的默认析构函数

我不明白为什么有必要在这里调用析构函数。如果我们有一个用户定义的析构函数,为它的一些类成员取消分配内存,我可以理解这里的用法,但是对于默认析构函数,我不知道为什么要这样做

一个对象的默认析构函数做什么,需要我们在释放为该对象分配的内存之前调用它?

对象的默认析构函数做什么

它为对象的数据成员调用析构函数(如果有)

这需要我们在释放为对象分配的内存之前调用它吗

唯一应该显式调用析构函数的时间是在预先存在的内存块中使用构造对象时。使用
placement new
将对象构造/销毁任务与内存分配/释放任务分离,因此您需要显式构造和销毁对象,但不必分配/释放其内存块,您可以在其他地方以任何方式管理它

如果不使用
placement new
构造对象,而是使用
new
分配+构造对象,则必须使用
delete
销毁+解除分配对象(最好使用智能指针,
std:unique\u ptr
std::shared\u ptr
,为您处理该问题)


如果不使用任何形式的< <代码> < <代码> >构造对象,则不要试图手动销毁对象。对象是自动存储的,编译器将为您管理。

< P>分配函数不了解C++对象。与<代码> > < <代码> >和>代码>删除<代码>分配内存NEE调用构造函数/析构函数时,C函数所做的全部工作就是分配/取消分配适当大小的内存,以便使用

因此,当您使用C函数时,您必须调用分配函数来获取内存,在其上调用placement new来实际在内存中构造对象(这是实际拥有该类型对象所必需的)。然后,当您使用完该函数后,您需要通过手动调用析构函数来销毁该对象(您需要这样做,以便对象的生存期正确结束),然后将指针传递到free,以便释放内存


这就是为什么你不应该在C++中使用<代码> * OLC/<代码>和<代码>免费>代码>。它们需要大量额外的工作而不是类型安全的。

< P>一个默认析构函数,当对象超出范围时,自动调用默认析构函数:

  • 函数结束
  • 节目结束了
  • 包含局部变量的块结束
  • 一个删除操作符被调用
  • 默认析构函数总是调用其成员对象的析构函数(不是用于指向对象的成员变量)。如果我们动态分配内存,它应该由我们处理,否则默认析构函数将清除局部变量

    如果我们不在类中编写自己的析构函数,编译器将为我们创建一个默认析构函数。除非我们在类中动态分配了内存或指针,否则默认析构函数可以正常工作。
    当一个类包含一个指向类中分配的内存的指针时,我们应该编写一个析构函数,在类实例被销毁之前释放内存。必须这样做,以避免内存泄漏。

    当对象超出范围时,调用
    dtor
    。您不必手动调用其中任何一个。如果u使用placement new构造对象。不要使用此问题中的语法。这会使问题本身不清楚。很可能您看到:
    exampleObject->~ClassName()
    ,其中
    ClassName
    是用于创建
    exampleObject
    的类。只有在使用
    malloc
    而不是
    new
    分配内存,并使用placement
    new
    初始化时,您才会看到这一点。placement new确实用于构造对象,我将编辑问题以包括这一点--也许你可以写一个解释原因的答案?为了清楚起见,更新了代码示例。如果你使用了new和delete,你不需要显式调用dtor。@如果你使用了non-placement
    new
    ,那么就可以了。如果你使用了
    placement new
    ,就不要使用
    delete