放置新行为等效

5 c++ memory-management placement-new new-operator

我对newC++中的放置语法有疑问.以下两个代码片段在功能上是否相同并且可以互换使用(我并不是说第二个应该使用,当第一个适合时)?

#1

T* myObj = new T();
// Do something with myObj
delete myObj;
Run Code Online (Sandbox Code Playgroud)

#2

char* mem = new char[sizeof(T)];
T* myObj = new (mem) T();
// Do something with myObj
myObj->~T();
delete[] mem;
Run Code Online (Sandbox Code Playgroud)

当我使用这样的放置新语法时,我应该特别小心吗?

Man*_*rse 11

它们不等同,因为它们具有不同的行为,如果构造函数或T抛出的析构函数.

new T()在释放异常之前,将释放已分配的所有内存.char* mem = new char[sizeof(T)]; T* myObj = new (mem) T();不会(除非你明确做某事以确保它被释放你将有泄漏).同样,delete myObj无论是否~T()抛出,都会释放内存.

确切的等价物T* myObj = new T();/*other code*/delete myObj;将是这样的:

//When using new/delete, T::operator new/delete
//will be used if it exists.
//I don't know how do emulate this in
//a generic way, so this code just uses
//the global versions of operator new and delete.
void *mem = ::operator new(sizeof(T));
T* myObj;
try {
    myObj = new (mem) T();
}
catch(...) {
    ::operator delete(mem);
    throw;
}
/*other code*/
try {
    myObj->~T();
    ::operator delete(mem);
}
catch(...) {
    //yes there are a lot of duplicate ::operator deletes
    //This is what I get for not using RAII ):
    ::operator delete(mem);
    throw;
}
Run Code Online (Sandbox Code Playgroud)

  • @TadeuszKopec:该标准保证内存具有最大可能的对齐.这仅适用于您使用自然对齐(即,与内置类型一起出现),如果您使用编译指示将类型的对齐方式(例如,最大值的两倍),则所有投注均已关闭. (3认同)

Jer*_*fin 8

由于您正在分配原始内存,因此更接近的是:

void *mem = operator new(sizeof(T));
T *myobj = new(mem) T();

// ...

myobj->~T();
operator delete(mem);
Run Code Online (Sandbox Code Playgroud)

请注意,如果您::operator new为某个特定类重载了,那么这将使用该类operator new,您使用new char []它将忽略它.

编辑:虽然我应该补充一点,我忽略了例外的可能性.@ Mankarse的回答似乎(对我而言)能够很好地涵盖这一部分.