如果我将operator delete定义为如下,并且如果对象构造函数抛出新表达式,我希望看到调用定义运算符的结果delete:
#include <new>
#include <cstdlib>
#include <iostream>
void*
operator new(std::size_t s){
std::cout << "alloc " << std::endl;
return std::malloc(s);
}
void
operator delete(void* p) noexcept {
std::cout << "dealloc " << std::endl;
std::free(p);
}
void
operator delete(void* p,std::size_t) noexcept{
std::free(p);
std::cout << "dealloc s" << std::endl;
}
struct A{
A(int i){
if(i>0)
throw 10;
}
};
int main(int argc// will equal 10
,char* arg[])
{
for(int i=0;i<argc;++i)
auto p=new A{argc};
return 0;
}
这个程序只输出alloc
,为什么不调用operator delete?在标准[expr.new]中指定:
如果上述对象初始化的任何部分通过抛出异常和合适的终止而终止 可以找到deallocation函数,调用deallocation函数来释放对象所在的内存 正在构建,之后异常继续在new-expression的上下文中传播。
答案 0 :(得分:2)
正如其他人已经指出的那样,这是因为你没有抓住异常。正如标准所说:
C ++11§15.3/ 9 :
“如果找不到匹配的处理程序,则调用函数std::terminate()
;在对std::terminate()
的调用是否为实现定义之前,堆栈是否已展开。“
虽然我认为这与你的情况下的堆栈没有特别的关系,但同样的原则也会存在。因此,如果清理了任何内存,实际上取决于实现。正如我们在这里看到的那样,通常情况并非如此,因为无论如何操作系统都会清理内存。
答案 1 :(得分:1)
答案 2 :(得分:1)
如果在构造期间使用new
,构造函数会抛出异常,即C ++运行时库:
std::terminate()
。是否调用delete
是实现定义的。或
delete
,虽然没有调用析构函数 - 即~A()
,如果有的话,将不会被调用当i
大于1时。