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

delete与析构函数的显式调用[重复]

子车煌
2023-03-14

在c语言中,对分配了new的对象调用delete,调用类的析构函数,并释放内存。如果不删除对象,而是显式调用其析构函数,然后释放内存,会有什么不同吗?

例如,考虑以下示例。

#include <iostream>

struct A {
  int i;
  ~A() { std::cout << "Destructor, i was " << i << std::endl; }
};

int main()
{
  A* p = new A{3};
  p->~A();
  free(p);

  return 0;
}

用7.3.0和6.0.1以及Wextra-Wall-pedantic编译代码不会产生任何警告。正如预期的那样,程序的输出是

Destructor, i was 3

使用valgrind/memcheck运行程序会出现不匹配的释放/删除错误:

==27743== Memcheck, a memory error detector
==27743== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==27743== Using Valgrind-3.14.0 and LibVEX; rerun with -h for copyright info
==27743== Command: ./destructor
==27743== 
Destructor, i was 3
==27743== Mismatched free() / delete / delete []
==27743==    at 0x4C3033B: free (vg_replace_malloc.c:530)
==27743==    by 0x4009FC: main (in /tmp/destructor)
==27743==  Address 0x5bbac80 is 0 bytes inside a block of size 4 alloc'd
==27743==    at 0x4C2F77F: operator new(unsigned long) (vg_replace_malloc.c:334)
==27743==    by 0x4009DA: main (in /tmp/destructor)
==27743== 
==27743== 
==27743== HEAP SUMMARY:
==27743==     in use at exit: 0 bytes in 0 blocks
==27743==   total heap usage: 3 allocs, 3 frees, 73,732 bytes allocated
==27743== 
==27743== All heap blocks were freed -- no leaks are possible
==27743== 
==27743== For counts of detected and suppressed errors, rerun with: -v
==27743== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

但是,没有内存泄漏。

我当然知道,在上面的代码中处理对象的标准方法是调用delete。我的问题比较正式:

  • delete是否完全等同于调用析构函数free?标准是否规定了这一点,或者我用上面的代码遇到了UB

共有1个答案

漆雕安晏
2023-03-14

虽然显式调用析构函数是合法的,但您希望这样做的情况非常罕见(例如,在较大缓冲区内构造和销毁对象的情况下)。

请注意,您应该始终将分配器与适当的内存释放、malloc/free、new/delete等匹配。虽然运算符new()通常在后台依赖malloc,但并不要求它这样做,在这种情况下,您的不匹配将产生未定义的结果。

 类似资料:
  • 构造函数与析构函数是自动调用的。这些函数的调用顺序取决于执行过程进入和离开实例化对象范围的顺序。一般来说,析构函数的调用顺序与构造函数相反。但图6.9将介绍对象存储类可以改变析构函数的调用顺序。 全局范围中定义的对象的构造函数在文件中的任何其他函数(包括 main)执行之前调用(但不同文件之间全局对象构造函数的执行顺序是不确定的)。当main终止或调用exit函数时(见第18章)调用相应的析构函数

  • 本文向大家介绍C++中构造函数与析构函数的调用顺序详解,包括了C++中构造函数与析构函数的调用顺序详解的使用技巧和注意事项,需要的朋友参考一下 前言 在使用构造函数和析构函数时,需要特别注意对它们的调用时间和调用顺序。在一般情况下,调用析构函数的次序正好与调用构造函数的次序相反:最先被调用的构造函数,其对应的(同一对象中的)析构函数最后被调用,而最后被调用的构造函数,其对应的析构函数最先被调用。

  • 条款6:析构函数里对指针成员调用delete 大多数情况下,执行动态内存分配的的类都在构造函数里用new分配内存,然后在析构函数里用delete释放内存。最初写这个类的时候当然不难做,你会记得最后对在所有构造函数里分配了内存的所有成员使用delete。 然而,这个类经过维护、升级后,情况就会变得困难了,因为对类的代码进行修改的程序员不一定就是最早写这个类的人。而增加一个指针成员意味着几乎都要进行下

  • 本文向大家介绍php构造函数与析构函数,包括了php构造函数与析构函数的使用技巧和注意事项,需要的朋友参考一下 php构造函数是对象创建完成后,第一个自动调用的方法,析构函数是当对象被释放之前最后一个自动调用的方法。本文章向大家介绍php构造函数与析构函数。 php构造函数 1.是对象创建完成后,“第一个”“自动调用”的方法 2.构造方法的定义,方法名是一个固定的, 在php4中:和类名相同的方法

  • 像这段代码一样,C编译器将把char*转换为bool,然后调用第一个函数,这与我的初衷不一致。有没有办法阻止编译器执行我不想要的类型转换?比如“-fno permissive”,但不幸的是,它不起作用。

  • 上面写着编译错误 Employee::new、1L、“”、“ 无法解析构造函数。