C++ 安全放置新&;显式析构函数调用
这是我的代码示例:C++ 安全放置新&;显式析构函数调用,c++,constructor,destructor,placement-new,C++,Constructor,Destructor,Placement New,这是我的代码示例: template <typename T> struct MyStruct { T object; } template <typename T> class MyClass { MyStruct<T>* structPool; size_t structCount; MyClass(size_t count) { this->structCount = count;
template <typename T> struct MyStruct {
T object;
}
template <typename T> class MyClass {
MyStruct<T>* structPool;
size_t structCount;
MyClass(size_t count) {
this->structCount = count;
this->structPool = new MyStruct<T>[count];
for( size_t i=0 ; i<count ; i++ ) {
//placement new to call constructor
new (&this->structPool[i].object) T();
}
}
~MyClass() {
for( size_t i=0 ; i<this->structCount ; i++ ) {
//explicit destructor call
this->structPool[i].object.~T();
}
delete[] this->structPool;
}
}
模板结构MyStruct{
T对象;
}
模板类MyClass{
MyStruct*structPool;
大小/结构计数;
我的班级(人数){
此->结构计数=计数;
this->structPool=newmystruct[count];
对于(size_t i=0;istructPool[i].object)t();
}
}
~MyClass(){
对于(大小i=0;istructCount;i++){
//显式析构函数调用
this->structPool[i].object.~T();
}
删除[]此->结构池;
}
}
我的问题是,这样做安全吗?在某些情况下我会犯一些隐藏的错误吗?它是否适用于每种类型的对象(POD和非POD)?否,因为构造函数和析构函数都会被调用两次。因为你有:
template <typename T> struct MyStruct {
T object;
}
然后,您需要放置new和explict析构函数调用。否,因为构造函数和析构函数都被调用了两次。因为你有:
template <typename T> struct MyStruct {
T object;
}
然后,您可能会想要放置新的、明确的析构函数调用。不,这肯定不是一种远程安全的方法。当您对非POD
T
执行new MyStruct[count]
操作时,数组中的每个MyStruct
对象都已默认构造,这意味着将自动调用对象
成员的构造函数。然后尝试在此基础上执行就地构造(通过值初始化)。结果行为未定义
删除也存在同样的问题
你想达到什么目的?只需执行newmystruct[count]()
(注意额外的空()
),它就已经为数组的每个元素执行了值初始化(这正是您之后尝试“手动”执行的操作)。为什么您觉得必须通过就地施工来完成
同样,当你这样做的时候
delete[] this->structPool;
它会自动为数组中的每个
MyStruct::object
成员调用析构函数。不需要手动操作。不,这肯定不是一种远程安全的操作方式。当您对非PODT
执行new MyStruct[count]
操作时,数组中的每个MyStruct
对象都已默认构造,这意味着将自动调用对象
成员的构造函数。然后尝试在此基础上执行就地构造(通过值初始化)。结果行为未定义
删除也存在同样的问题
你想达到什么目的?只需执行newmystruct[count]()
(注意额外的空()
),它就已经为数组的每个元素执行了值初始化(这正是您之后尝试“手动”执行的操作)。为什么您觉得必须通过就地施工来完成
同样,当你这样做的时候
delete[] this->structPool;
它会自动为数组中的每个MyStruct::object
成员调用析构函数。不需要手动操作
template <typename T> class MyClass {
void* structPool;
size_t structCount;
MyClass(size_t count)
: structPool(new char[sizeof(T)*count], structCount(count)
{
//placement new to call constructor
for( size_t i=0 ; i<count ; i++ )
new (structPool+i*sizeof(T)) T();
}
~MyClass() {
//explicit destructor call
for( size_t i=0 ; i<structCount ; i++ )
reinterpret_cast<T*>(structPool+i*sizeof(T))->~T();
delete[] structPool;
}
}
template <typename T> class MyClass {
void* structPool;
size_t structCount;
MyClass(size_t count)
: structPool(new char[sizeof(T)*count], structCount(count)
{
//placement new to call constructor
for( size_t i=0 ; i<count ; i++ )
new (structPool+i*sizeof(T)) T();
}
~MyClass() {
//explicit destructor call
for( size_t i=0 ; i<structCount ; i++ )
reinterpret_cast<T*>(structPool+i*sizeof(T))->~T();
delete[] structPool;
}
}
template <typename T> class MyClass {
void* structPool;
size_t structCount;
MyClass(size_t count)
: structPool(new char[sizeof(T)*count], structCount(count)
{
//placement new to call constructor
for( size_t i=0 ; i<count ; i++ )
new (structPool+i*sizeof(T)) T();
}
~MyClass() {
//explicit destructor call
for( size_t i=0 ; i<structCount ; i++ )
reinterpret_cast<T*>(structPool+i*sizeof(T))->~T();
delete[] structPool;
}
}
如果您正在使用malloc和placement new,则调用每个析构函数并执行一个C风格的freeif
this->structPool=new MyStruct[count]如何代码>替换为this->structPool=(MyStruct*)malloc(sizeof(MyStruct)*count)代码>。在这种情况下,我们需要放置新的显式析构函数?是的,您需要这样做,但您需要为MyStruct本身调用构造函数/析构函数,而不是为MyString.object调用构造函数/析构函数。@uray-是的,如果您使用malloc获取原始内存,则需要放置新的/显式析构函数。也就是说,看起来你是在寻找使用placement new/explicit析构函数的理由,而不是真正需要它。@Samuel:哈哈,不,我不是在寻找理由,我只是想确保我的理解是正确的。@uray-明白了。我的建议是去掉MyStruct
,因为这会混淆问题。如果this->structPool=newmystruct[count]代码>替换为this->structPool=(MyStruct*)malloc(sizeof(MyStruct)*count)代码>。在这种情况下,我们需要放置新的显式析构函数?是的,您需要这样做,但您需要为MyStruct本身调用构造函数/析构函数,而不是为MyString.object调用构造函数/析构函数。@uray-是的,如果您使用malloc获取原始内存,则需要放置新的/显式析构函数。也就是说,看起来你是在寻找使用placement new/explicit析构函数的理由,而不是真正需要它。@Samuel:哈哈,不,我不是在寻找理由,我只是想确保我的理解是正确的。@uray-明白了。我的建议是去掉MyStruct
,因为这会混淆问题。如果T
的构造函数需要参数来构造,T
具有T()
和T(arg,…)
构造函数,但我需要在构造过程中提供参数,该怎么办?我可以继续吗
template <typename T> class MyClass {
void* structPool;
size_t structCount;
MyClass(size_t count)
: structPool(new char[sizeof(T)*count], structCount(count)
{
//placement new to call constructor
for( size_t i=0 ; i<count ; i++ )
new (structPool+i*sizeof(T)) T();
}
~MyClass() {
//explicit destructor call
for( size_t i=0 ; i<structCount ; i++ )
reinterpret_cast<T*>(structPool+i*sizeof(T))->~T();
delete[] structPool;
}
}