首页 > 解决方案 > 为什么运算符删除重载不会在调用删除时调用无限递归调用

问题描述

由于无限递归调用,调用 operator new 的局部重载会导致堆栈溢出,但是当 operator delete 的局部重载发生同样的情况时,为什么会调用全局 operator 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?

标签: c++delete-operator

解决方案


我正在尝试将我的评论总结为答案。

delete关键字,而不是函数或运算符。所以它的行为不像函数。

当您编写 时delete p,编译器不会像函数一样执行重载查找。当编译器遇到表达式时,它会在指针类型的delete p可用重载之间进行查找。If是指向类的指针,并且存在特定于类的重载 then被调用。否则,编译器会在 scoped 之间执行查找。operator deleteppp->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);,您将再次获得无限递归。


推荐阅读