我有一个班级A
。我正在使用的一些库为我分配给定量的内存,sizeof A,并返回一个指向它的void指针。
A* pObj = (A*) some_allocator_im_forced_to_use( sizeof A );
现在如何在刚分配的内存中创建A
的新实例?
我尝试过:
*pObj = A();
但这不起作用 - 析构函数在A的构造函数之后被调用。
答案 0 :(得分:8)
您可以使用展示位置新内容:
A* pObj = new ( some_allocator_im_forced_to_use( sizeof( A ) ) ) A;
这会在函数A
返回的位置构造一个新的some_allocator_im_forced_to_use
实例。此函数需要返回一个void*
,指向适当的内存,并为相关实现上的A
对象进行适当的对齐。
您可能需要手动为此对象手动调用析构函数,因为您将无法使用通常的delete pObj
来销毁它。
pObj->~A();
// Call custom allocator's corresponding deallocation function on (void*)pObj
为了正确销毁对象并释放内存,您可以考虑将shared_ptr
与自定义删除器一起使用。
答案 1 :(得分:3)
使用展示位置新功能:
new (pObj) A;
您还需要以不同方式销毁对象,因为delete
假设(错误地)您使用普通的new
创建了对象:
pObj->~A();
some_deallocator_im_forced_to_use( pObj );
答案 2 :(得分:2)
您需要'放置新'
答案 3 :(得分:1)
答案 4 :(得分:1)
有些人主张安置新的。
这很危险,到目前为止两个使用示例已经省略了关键细节,例如包括<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;
}
重要说明:虽然这本身就是“安全的”,虽然这个特殊的例子是安全的,但你的代码的安全性最终取决于你的自定义分配器返回指向正确对齐的内存的指针。
干杯&amp;第h。,
答案 5 :(得分:0)
如果您的分配器遵循std::allocator
模型,它应该有几种方法:
allocate
construct
destroy
deallocate
它们几乎是不言自明的,重要的是你有责任给它们打电话:
或者你会得到UB或泄漏。
然而,我有点惊讶的是,只有分配器需要大小,通常它还需要对象的对齐,除非只是使用目标上可能的最大对齐,而不管要分配的对象。