调用运算符new的局部重载会导致无限次递归调用,从而导致堆栈溢出,但是当运算符delete的局部重载发生这种情况时,为什么要调用全局运算符delete(因此避免了堆栈崩溃)。
简单的代码像这样-
class A {
public:
void * operator new(size_t n) {
//return new A();calls local overloaded version and stack overflows
return ::new A();
}
void operator delete(void* p)
{
delete(p);//why its calling global version?
//::delete(p);//calls global version
}
};
int main()
{
A *a = new A();
delete(a);
}
我的问题是,为什么从重载运算符删除中删除不会自动调用而是全局运算符删除?
最佳答案
我试图将我的评论总结成答案。delete
是关键字,不是函数或运算符。因此它的行为不像函数。
当您编写delete p
时,编译器不会对函数之类的重载执行查找。当编译器满足表达式delete p
时,它将在可用重载operator delete
之间针对指针p
的类型执行查找。如果p
是指向类的指针,并且存在类特定的重载,则将调用p->operator delete(some_ptr)
。否则,编译器将在作用域void operator delete(void*)
之间执行查找。
回到你的例子。
A *a = new A();
delete(a); // a is pointer to class, calls a->operator delete(a);
void A::operator delete(void* p) {
delete(p); // p is pointer to void, calls ::operator delete(p);
}
如果调用
operator delete(a);
,则就像函数调用一样,并且不调用A::operator delete(void*);
。如果从
operator delete(p);
内部调用A::operator delete(void* p);
,则会得到无限递归。如果从
delete static_cast<A*>(p);
内部调用A::operator delete(void* p);
,则会再次获得无限递归。
关于c++ - 为什么运算符删除重载不会在调用删除时调用无限递归调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61034068/