条款52:写了 placement new 也要写 placement delete
在自定义内存分配时,如果你定义了 placement new
,那么你必须同时定义 placement delete
。否则,程序可能会发生隐性和间歇性的内存泄漏。
使用场景
-
Placement new:
placement new
是一种特殊的内存分配方式,它允许将对象直接构造到已分配的内存块中。placement new
接受除了size_t
外的其他参数,通常是一个指向预分配内存的指针。 -
Placement delete:
与placement new
配套使用的placement delete
用于销毁在指定内存位置上构造的对象。它的作用是销毁对象,而不会释放内存,因为内存是由外部分配的。
示例:定义 placement new
和 placement delete
// 定义 placement new void* operator new(std::size_t, void* pMemory) throw() { return pMemory; // 返回已分配的内存 } // 定义 placement delete void operator delete(void* pMemory, void* pObject) throw() { // 注意:这里不会释放内存,仅销毁对象 if (pMemory != nullptr) { // 通过调用对象的析构函数销毁对象 static_cast<Base*>(pMemory)->~Base(); } }
在此示例中,placement new
将对象直接构造在预先分配的内存 pMemory
中,而 placement delete
不会释放内存,仅调用对象的析构函数进行清理。
注意事项
-
避免内存泄漏:
如果你编写了placement new
,但没有为其提供配套的placement delete
,那么已分配的内存将不会被正确清理,导致内存泄漏。必须确保两者都得到定义。 -
不遮掩正常版本的
new
和delete
:
当定义placement new
和placement delete
时,确保不要无意间遮掩掉正常版本的operator new
和operator delete
。否则,可能会导致错误的内存管理行为。 -
与标准
new
和delete
的区别:
placement new
和placement delete
不涉及内存分配和释放,它们只是在指定内存位置构造和销毁对象。而标准的new
和delete
则会负责内存的分配和释放。
总结
在使用 placement new
的同时,必须实现相应的 placement delete
,以确保对象被正确销毁且内存不会泄漏。正确地处理内存管理和对象生命周期,能够有效地避免内存问题,提高代码的可靠性。记得不要遮掩标准的 new
和 delete
操作符,这有助于保持内存管理的一致性和清晰性。