12.5/4 [class.free]
部分:
如果查找结果不明确或不可访问,或者如果 查找选择一个放置重新分配函数,该程序是 不良形成。
所以,例如,如果我们写:
class A
{
public:
void* operator new ( std::size_t count, std::size_t msg, std::size_t mmsg );
void operator delete ( void* ptr, std::size_t msg, std::size_t mmsg );
};
void* A::operator new ( std::size_t sz, std::size_t msg, std::size_t mmsg ){
std::printf("global op new called, message = %lu, %lu", msg, mmsg);
return std::malloc(sz);
}
void A::operator delete ( void* ptr, std::size_t msg, std::size_t mmsg ){
std::printf("global op new called, message = %lu, %lu", msg, mmsg);
}
放置释放函数永远不会被称为删除表达式的评估的一部分。因此,问一下它们的用途是合理的。我们只能通过手动调用operator[](void*, std::size_t, std::size_t)
来调用它们,这是不方便的。
答案 0 :(得分:5)
在new
- 表达式求值期间,当构造函数调用抛出时,将调用放置释放函数来清理。此时,传递给放置分配的信息仍然可用,并且可以再次传递给释放功能。稍后,在成功new
- 表达式之后,该信息不可用,因此普通的释放函数由delete
语句使用。
基本上,如果取消分配依赖于传递给放置分配函数的信息,则用户代码负责保留成功创建的对象的信息。另一种方法可能是指定C ++实现如何保留它,以便它可以遵守隐含的任何限制。但是这会带来复杂性,并且会违反“不要使用C ++的设计原则”。
Microsoft的MFC类框架曾经有一个错误,他们忘记提供一个放置释放函数来匹配他们在调试new
中使用的放置分配函数,导致内存泄漏仅在调试版本中。愚蠢的。