有没有人知道C ++删除程序对于new new和regular new都是安全的?
Object* regular = new Object();
delete_procedure(regular);
void* buf = ::new(sizeof(Object));
Object* placement = new(buf) Object();
delete_procedure(placement);
这个功能似乎有效,但我无法弄清楚它是否对两个实例都是安全的(这是删除贴图新标准的方法)。
delete_procedure(Object* obj){ // Not sure if safe for regular new
obj->~Object();
::delete(obj);
}
答案 0 :(得分:3)
我不相信有任何统一的做法,而不会引入一些额外的标记来标记事物。 C ++理念是"你需要跟踪你如何分配事物并确保它们全部被正确销毁,"它出于效率目的而这样做。考虑delete[]
与delete
。可以有一个统一的delete
关键字来清理任何内存块,但由于确定需要调用哪个释放例程的成本,这会产生性能开销。或者考虑虚拟析构函数:C ++可以说delete
总是进行某种类型的内省,但这会增加所有对象类型的开销,其中大部分是不必要的。
C ++的哲学是“不为你不能使用的东西买单,"因此,如果您想构建统一的内容,您需要设置一些额外的基础架构来跟踪您需要执行的删除例程。
答案 1 :(得分:1)
不,因为数组和细节。当然,因为这些问题可能与您的代码库无关。
所有删除都是特定于类型的删除,或者:
除非ptr是空指针或者是先前从operator new(size_t)或operator new(size_t,std :: nothrow_t)的标准库实现获得的指针,否则此函数的标准库实现的行为是未定义的。
来自http://en.cppreference.com/w/cpp/memory/new/operator_delete
这意味着将new[](size_t)
分配给delete(void*)
的内存传递给UB,将new[](size_t)
传递给delete[](void*)
是UB。
其次,用户可以全局或按类替换新/删除。
第三
void delete_procedure(Object* obj){
obj->~Object();
::operator delete((void*)obj);
}
你想要转换为void指针并使用operator delete。
第四,传递给delete_procedure
的指针必须是new T
或::new( ::new(sizeof(T)) ) T
生成的指针;它不能是指向派生子对象的指针,因为它作为void*
的值可能不同。
如果T* pt
是动态可投射的,dynamic_cast<void*>( pt )
将重建void*
。所以这不像看起来那么障碍。记得在摧毁物体之前进行施法!
void delete_procedure_dynamic(Object* obj){
void* ptr=dynamic_cast<void*>(obj);
obj->~Object();
::operator delete(ptr);
}
并使用SFINAE / tag分派在动态和非动态版本之间进行分派。
第五,高对齐类型需要处理。他们使用不同的new和delete。我不确定动态转换和过度对齐的派生类型是如何相互作用的,但可能你不必关心。
但是new T
调用::new(size_t)`` then constructs an object there.
operator delete(void *)must be fed memory produced by
:: new(size_t). Destroying an object creates by
new T is legal via
。〜T()` 。所以我看不出任何根本原因。
在实践中,我可能会做的是覆盖“普通”new以遵循与额外存储新模式相同的模式(并通过new(size_t)
分配块)以保持简单。你处于一个神秘的领域,为什么不把事情统一起来。