【问题标题】:Why operator delete overloading doesn't call infinite recursive call on calling delete为什么运算符删除重载不会在调用删除时调用无限递归调用
【发布时间】:2020-04-04 20:03:18
【问题描述】:

调用 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


    【解决方案1】:

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

    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*);不会被调用。

    如果你从A::operator delete(void* p); 内部调用operator delete(p);,你会得到无限递归。

    如果您从A::operator delete(void* p); 内部调用delete static_cast<A*>(p);,您将再次获得无限递归。

    【讨论】:

    • 所以,您的意思是新建和删除 w.r.t 之间的区别。无限递归只是由于参数的类型(因为运算符删除需要处理 void * 或 A*)?
    猜你喜欢
    • 2015-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-09
    • 2011-03-23
    • 2016-07-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多