删除展示位置或非展示位置新内容

时间:2017-09-28 20:11:43

标签: c++ memory-management destructor

有没有人知道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);
}

2 个答案:

答案 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)分配块)以保持简单。你处于一个神秘的领域,为什么不把事情统一起来。