我有一个C ++对象,它是在宿主应用程序提供的内存缓冲区中的插件中创建的,其中placement new运算符的方式类似于以下代码:
MyClass* createObject(void* inNewBlock)
{
MyClass* elementAddr = static_cast<MyClass*>(inNewBlock);
new (elementAddr) MyClass(); // Placement new into pre-allocated memory
}
我知道我无法删除以这种方式创建的对象,但我想知道是否有办法使内存无效并在以后重新分配对象,如果我需要这样:
void removeObject(MyClass* object)
memset(object, NULL, sizeof(MyClass));
}
void restoreObject(MyClass* object)
{
new (object) MyClass(); // Placement new into pre-allocated memory
}
上面的代码不起作用。我试过了,当我拨打restoreObject()
时,主机应用程序挂起或崩溃。我希望有人可以向我解释为什么这不起作用以及可能的替代方案。
答案 0 :(得分:7)
这太复杂了。当你不再需要它时,你可以简单地销毁它。另外,placement-new参数已经是一个void指针,不需要强制转换。这与标准库分配器的作用非常相似:
MyClass * create(void * addr)
{
return ::new (addr) MyClass; // default-initialize
}
MyClass * create(void * addr, const MyClass & x)
{
return ::new (addr) MyClass(x); // copy-construct from prototype
}
void destroy(MyClass * p)
{
p->~MyClass(); // you can now reuse the memory
}
没有“恢复”这样的东西;你可以在内存中创建一个新对象,如果你已经正确地销毁了那个对象,那么该对象将被另一个对象使用。
编辑:我添加了另一个构造方法,它可以复制给定对象,以防你的类不是默认构造的。
答案 1 :(得分:4)
在将该内存设置为0之前,需要在对象上调用析构函数。例如:
void removeObject(MyClass* object)
{
object->~MyObject();
memset(object, NULL, sizeof(MyClass);
}
否则对象将不会释放其资源。
除此之外,你正在做的事情本身没有任何错误。如果在以上述方式修改它之后崩溃,则主机应用程序存储与每个对象不兼容的东西,并尝试将其与不同的对象一起使用。您必须显示它在主机应用程序中的使用方式。
答案 2 :(得分:2)
如果您使用placement new,则必须直接调用析构函数:
MyClass* elementAddr = new (inNewBlock) MyClass();
//Do stuff
elementAddr->~MyClass();
//inNewBlock is now free to be used for other purposes.
答案 3 :(得分:0)
我强烈建议您传递内存缓冲区的大小,以防止发生不良事件。
还要注意放置新内容的一个重大缺陷:内存对齐。请参阅placement new + array +alignment。
传入超大缓冲区可以提供帮助。
MyClass* createObject(void* inNewBlock, size_t size)
{
// basic sanity check
assert(size >= sizeof(MyClass);
MyClass* result = new (inNewBlock) MyClass();
// result might not be the same as elementAddr
// check that the result fits in-to the space provided.
assert(result + sizeof(MyClass) <= (char*)inNewblock + size);
return result;
}
我知道我无法删除以这种方式创建的对象
实际上你可以(如其他答案所示):
void deleteObject(MyClass* c)
{
c->~MyClass();
}
MyClass* restoreObject(MyClass* c)
{
return createObject(c, sizeof(MyClass));
}