c++ - 删除与显式调用析构函数
问题描述
在 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
会出现不匹配的释放/删除错误:
==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 等相匹配。虽然 operator new() 在底层依赖 malloc 是典型的,但并不要求它这样做,因为如果您的不匹配会产生未定义的结果。
推荐阅读
- ravendb - RavenDB 一致性 - WaitForIndexesAfterSaveChanges() / WaitForNonStaleResultsAsOfNow
- c# - 如何在 XAML (WPF) 的 Listview 中删除分隔标题的边框?
- asp.net - 如何将文件放入文件夹并生成 .zip 文件?
- mysql - MySQL:使用“两半”方法查找中位数
- android - 为什么异步任务处理是直接的,而加载程序处理是间接的?
- android - AspectFit 不适用于保存到 Android 设备的图像
- python - Python3 对照另一个检查字典列表
- java - 如何在片段的 onCreateview 上更新我的对象数组列表
- python - 否 模块名称 Crypto
- azure - Azure 消息服务:检测消息的缺失