删除与析构函数的显式调用
delete vs explicit call of destructor
在 c++ 中,调用 delete
分配了 new
的对象调用类的析构函数,并释放内存。如果不删除对象,而是显式调用其析构函数,然后释放内存,会有什么区别吗?
例如,考虑以下示例。
#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;
}
使用 g++
7.3.0 和 clang
6.0.1 以及 -Wextra -Wall -pedantic
编译代码不会引发任何警告。正如预期的那样,程序的输出是
Destructor, i was 3
使用 valgrind
/memcheck
运行程序会给出不匹配的 free/delete 错误:
==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)
但是,没有内存泄漏。
我当然知道,处理上面代码中p
的对象的标准方法是调用delete
。我的问题更正式:
delete
完全等效于对析构函数的调用和free
?标准是否指定了这一点,或者我遇到了 UB用上面的代码?
虽然显式调用析构函数是合法的,但您希望这样做的情况非常罕见(例如,std::vector 在较大的缓冲区中构造和销毁对象)。
请注意,您应该始终将分配器与适当的内存版本、malloc/free、new/delete 等相匹配。虽然运算符 new() 在引擎盖下依赖 malloc 是典型的,但没有要求它这样做,在这种情况下,您的不匹配会产生未定义的结果。
相关文章:
- 什么时候调用析构函数
- C++-明确何时以及如何调用析构函数
- C++ 防止在映射中放置()时调用析构函数
- 调用析构函数以释放动态分配的内存
- C++:使用方法调用析构函数的顺序是什么?
- 向量推回调用析构函数时调用析构函数
- 如何在调用析构函数时优雅地停止/销毁带有阻塞调用C++线程?
- C++,我应该调用析构函数吗?
- 如何获取有关在 Clang LibTooling 中调用析构函数的信息?
- 当我从 std::vector 中的新放置调用析构函数时会发生什么?
- 为什么这里不调用析构函数
- 在调用 std::bind 的产品后意外调用析构函数
- 为什么在传递给函数而不是构造函数时调用析构函数?
- 如何在C++中调用析构函数
- 为什么为未删除的对象调用析构函数?
- 调用析构函数时出错
- C++ 在不释放内存的情况下调用析构函数
- 为什么在运算符删除中不调用析构函数?
- C++ 调用析构函数后动态模板队列"double free or corruption (out)"
- 在 postOrderDelete 上调用析构函数时引发的异常