今天,看到一个有趣的面试题,问题是:在C++里如何释放内存的时候不调用对象的析构函数?
之所以有趣,是因为这个问题违反了C++中资源管理的RAII(资源获取即初始化),它要求资源的释放应当和对象的生命周期紧密相关。在正常情况下,当对象离开其作用域时,它的析构函数被调用,以释放它所管理的资源,比如内存、文件句柄或网络连接等。
然而,这个问题提出了一种特殊情况,在出于性能优化、特殊的内存管理策略,或是为了与低级操作系统功能或硬件直接交互的需求。在这些情况下,我们可能需要释放对象占用的内存,但又不希望执行其析构函数。
在C++中,如果真的需要这么做,有什么方法呢?我们一起来梳理看看。
placement new方式
可以通过使用 placement new 来在预先分配的内存块上构造对象,然后不显式调用它的析构函数。
#include <new> // 需要包含头文件new
char buffer[sizeof(MyClass)]; // 分配足够的内存来存放MyClass对象
MyClass* obj = new(buffer) MyClass(); // 在buffer上构造对象
// ... 使用obj
// 显式调用析构函数是这样的:
// obj->~MyClass();
// 如果你不调用析构函数,对象的生命周期将结束,
// 但是它的析构函数不会被执行。但是由于对象用的是栈上的内存,内存会正常释放。
使用 placement new 需要你非常明确地知道自己在做什么,因为这样做会绕过正常的构造和析构过程。这可能导致资源泄露、内存未正确释放或其他未定义行为。
MyClass* obj = new MyClass(); // 常规地分配对象
// ... 在这里使用obj
operator delete(obj); // 释放内存但不调用析构函数
placement new的chromium的封装
chromium里面对placement new的设计模式提供了一套模板支持,如下:
template <typename T>
class NoDestructor {
public:
// Not constexpr; just write static constexpr T x = ...; if the value should
// be a constexpr.
template <typename... Args>
explicit NoDestructor(Args&&... args) {
new

最低0.47元/天 解锁文章
714

被折叠的 条评论
为什么被折叠?



