我有一个类A
。我正在使用的一些库为我分配了一定量的内存,sizeof A,并返回一个void指针。C++:在分配的内存中存储类实例
A* pObj = (A*) some_allocator_im_forced_to_use(sizeof A);
现在我怎么可以创建A
一个新的实例,在刚刚分配的内存?
我有尝试过:
*pObj = A();
但这并没有工作 - 析构函数得到了A的构造
我有一个类A
。我正在使用的一些库为我分配了一定量的内存,sizeof A,并返回一个void指针。C++:在分配的内存中存储类实例
A* pObj = (A*) some_allocator_im_forced_to_use(sizeof A);
现在我怎么可以创建A
一个新的实例,在刚刚分配的内存?
我有尝试过:
*pObj = A();
但这并没有工作 - 析构函数得到了A的构造
您可以使用新的位置后立即叫:
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);
你需要 '放置新的'
如果您分配如下std::allocator
模型应当有几种方法:
allocate
construct
destroy
deallocate
他们是非常不言自明的,最重要的是,你有责任美其名曰:
或者你会得到UB或泄漏。但是我有点惊讶,只有大小是你的分配器所需要的,通常它还需要对象的对齐,除非是简单地使用目标上可能的最大对齐方式,而不管对象是否被分配。
有些人主张新安置。
这很危险,迄今为止的两个使用示例已经省略了关键细节,如包含<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;
}
重要提示:虽然这本身就是“安全”,尽管这个特殊的例子是安全的,您代码的安全最终取决于您的自定义分配器返回一个指针,以正确对齐的内存。
干杯&心连心,
+1覆盖新的运营商是绝对比使用放置新的更好的主意。 – 2010-12-08 16:03:15