在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
上面的代码?答案 0 :(得分:0)
虽然合法地调用析构函数是合法的,但在这种情况下,您极少会使用析构函数(例如,在较大缓冲区中构造和破坏对象的情况下,例如std :: vector)。
请注意,您应始终将分配器与适当的内存释放,malloc / free,new / delete等进行匹配。虽然操作符new()通常在幕后依赖于malloc,但并不需要这样做那样的话,您的不匹配将产生不确定的结果。