C ++不对称放置新放置和删除放置。我们被允许以几乎任意方式重载新的放置位置。但是,只能从放置新表达式中 调用放置删除功能。特别是,如果对象的构造函数引发异常,则会调用它们。根本无法调用应用程序代码的放置删除。
我有以下困惑和需要澄清的问题:
1)如果没有定义放置删除对应对象,为什么C ++编译器不能简单地拒绝放置新方法签名?这样做可以帮助消除这种情况下内存泄漏的可能性。
2)如果我有多个内存池(由应用程序代码管理),并且我希望新的放置位置可以从不同的池中分配内存,则由于没有办法知道哪个内存,因此根本无法支持这种情况。池指针来自运算符删除? (操作员删除仅具有void *信息)。有什么办法可以用C ++做到这一点?
struct Node {
void* operator new(size_t size, Strategy s) {
// Depend on different strategy, allocate memory
// from different Memory pool
}
void operator delete(void* memory, Strategy s) {
// Return the memory to different Memory pool
// depends on the Strategy
// However this delete will only be invoked by
// c++ runtime if Node constructor throws.
}
void operator delete(void* memory, size_t s) {
// This delete doesn't have any clue about the
// the strategy. Hence, it can't decide which
// Memory pool to return to.
}
}
3)在placement new的上下文中,C ++运行时将使用相同的参数调用placement delete。 C ++运行时如何做到这一点?
答案 0 :(得分:2)
此答案假设问题涉及user-defined placement allocation functions:
void* operator new ( std::size_t count, user-defined-args... );
void* operator new[]( std::size_t count, user-defined-args... );
和user-defined placement deallocation functions:
void operator delete ( void* ptr, args... );
void operator delete[]( void* ptr, args... );
这些功能的行为是:
operator new
:如果已定义,则由具有匹配签名的自定义单对象放置新表达式调用。如果定义了特定于类别的版本,则优先于此版本进行调用。如果用户都不提供,则放置新表达式的格式不正确。operator new[]
:同上,但用于数组形式。operator delete
:如果已定义,则在对象的构造函数引发异常时,由具有匹配签名的自定义单对象放置新表达式调用。如果定义了特定于类别的版本,则优先于此版本进行调用。如果用户都不提供,则不会调用释放函数。operator delete[]
:同上,但用于数组形式。要回答您的问题:
不支付不使用的费用。可能存在不需要取消分配功能的设置。
您将必须包含一种机制,通过该机制,可以使用要删除的void *
指针的值来确定其所在的内存池。这必须是可能的,因为您的不同池无法同时返回相同的值。一个简单的方法可能是让每个池管理一个不重叠的地址范围,并针对每个池的地址范围测试指针。或者,您可以在指向的位置之前将元数据存储在内存中,例如new
版本将分配N + 16字节,将元数据存储在前16个字节中,并向用户返回指向该块第16个字节的指针。或者,您可以保留将每个活动指针与元数据相关联的数据结构。
对用于分配类类型对象的new表达式的求值将类似于:
operator new
,并传递参数operator delete
存在,则调用该函数并传递参数。答案 1 :(得分:1)
已经进行了查找:您应该提供一个Node :: destroy,该节点将摆脱该节点并将其返回到本地堆中。
如果这些是new
的通用void*
,我们将进行以下销毁:
template<class T> void destroy (Strategy s, T* ptr)
{
ptr->~T();
// return to custom heap
}
您可以使用一些花哨的技巧来摆脱策略,例如检查堆ptr所在的位置,或将其存储在new
中的负偏移处。
无用的历史答案:
已经很久了,但是我记得语法是
delete (strategy) pointer;
这似乎是来自BC4.5的特定于供应商的废话。