【发布时间】:2011-05-22 06:57:11
【问题描述】:
我有一堂课A。我正在使用的某个库为我分配给定数量的内存 sizeof A,并返回一个指向它的 void 指针。
A* pObj = (A*) some_allocator_im_forced_to_use( sizeof A );
现在如何在刚刚分配的内存中创建A 的新实例?
我试过了:
*pObj = A();
但这不起作用 - 在 A 的构造函数之后立即调用了析构函数。
【问题讨论】:
我有一堂课A。我正在使用的某个库为我分配给定数量的内存 sizeof A,并返回一个指向它的 void 指针。
A* pObj = (A*) some_allocator_im_forced_to_use( sizeof A );
现在如何在刚刚分配的内存中创建A 的新实例?
我试过了:
*pObj = A();
但这不起作用 - 在 A 的构造函数之后立即调用了析构函数。
【问题讨论】:
你可以使用placement new:
A* pObj = new ( some_allocator_im_forced_to_use( sizeof( A ) ) ) A;
这会在函数some_allocator_im_forced_to_use 返回的位置构造一个新的A 实例。此函数需要返回一个 void* 指向足够的内存,并为相关实现中的 A 对象适当对齐。
您可能必须手动调用此对象的析构函数,因为您将无法使用通常的delete pObj 来销毁它。
pObj->~A();
// Call custom allocator's corresponding deallocation function on (void*)pObj
为了正确销毁对象并释放内存,您可以考虑使用带有自定义删除器的shared_ptr。
【讨论】:
使用新的展示位置:
new (pObj) A;
您还需要以不同的方式销毁对象,因为delete 假定(错误地)您使用普通的旧new 创建了对象:
pObj->~A();
some_deallocator_im_forced_to_use( pObj );
【讨论】:
你需要'新位置'
【讨论】:
【讨论】:
有些人主张安置新。
这很危险,到目前为止,两个使用示例都省略了重要的细节,例如包括 <new> 标头、限定调用(如 ::new ...)以及如何清理。
安全的解决方案是为您的类或从您的类派生的类定义自定义分配和释放函数。下面的示例显示了后者。请注意,虚拟析构函数仅用于支持类派生;如果你不派生,你就不需要它。
#include <stddef.h>
#include <iostream>
void* some_allocator_im_forced_to_use( size_t size )
{
std::cout << "Allocated " << size << " bytes." << std::endl;
return ::operator new( size );
}
void some_deallocator_im_forced_to_use( void* p, size_t size )
{
std::cout << "Deallocated " << size << " bytes." << std::endl;
::operator delete( p );
}
struct A
{
int x_;
A(): x_( 42 ) {}
virtual ~A() {}
};
struct CustomAllocedA
: A
{
void* operator new( size_t size )
{
return some_allocator_im_forced_to_use( size );
}
void operator delete( void* p, size_t size )
{
some_deallocator_im_forced_to_use( p, size );
}
};
int main()
{
A* const p = new CustomAllocedA;
std::cout << p->x_ << std::endl;
delete p;
}
重要提示:尽管这本身是“安全的”,并且尽管这个特定示例是安全的,但您的代码的安全性最终取决于您的自定义分配器返回指向正确对齐内存的指针。
干杯,
【讨论】:
如果你的分配器遵循std::allocator的模型,它应该有几个方法:
allocateconstructdestroydeallocate它们几乎是不言自明的,重要的是您有责任调用它们:
否则你会得到 UB 或泄漏。
但我有点惊讶的是,您的分配器只需要大小,通常它还需要对象的对齐,除非它只是简单地使用目标上可能的最大对齐方式,而不管要分配的对象是什么。
【讨论】: