【问题标题】:Does "delete" work properly with polymorphism? [duplicate]“删除”是否适用于多态性? [复制]
【发布时间】:2013-05-06 02:05:01
【问题描述】:
BaseClass * p = new DerivedClass();
delete p;

我知道如果基类没有虚拟析构函数,第二行将调用基类的析构函数,如果有,则调用派生类的析构函数,但 delete 会正确释放内存(假设为 BaseClass' s 对象占用 8 个字节的空间,DerivedClass 的一个 12 - 它会释放 8 个或 12 个字节)并在任何一种情况下都摆脱该对象?

【问题讨论】:

  • 你熟悉malloc/free语义吗?
  • Re: “调用基类的析构函数”——也许吧。如果通过指向基类型的指针删除派生类型的对象,并且基类型没有虚拟析构函数,则行为未定义。它可能会调用基类的析构函数,但这不是必须的。
  • @NPS 请注意,值得一提的是,如果您在堆栈上创建了 DerivedClass 对象(即 - DerivedClass d;),那么 BaseClass Dtor 是否为虚拟并不重要- 它们中的两个(都是 Dtor 的)将按照与它们的构造相反的顺序被调用(即 - DerivedClass 和 BaseClass )。

标签: c++ virtual-destructor


【解决方案1】:

好吧,如果它有一个virtual 析构函数,当然该对象将被销毁并按预期释放内存。如果它没有virtual 析构函数,则行为未定义。

如果待删除对象的静态类型与其动态类型不同,则静态类型应为待删除对象动态类型的基类,且静态类型应具有虚析构函数或行为未定义。

因此,尝试推断内存是否将被完全释放并没有任何意义。程序可以对内存做任何事情。

【讨论】:

    【解决方案2】:

    如果析构函数不是虚拟的,delete 不会删除派生类。

    我试过这个:

    #include<iostream>
    
    using namespace std;
    
    class Base {
    public:
        Base() {
            cout<<"Creating base."<<endl;
        }
    
        ~Base() {
            cout<<"Killing base."<<endl;
        }
    };
    
    class Derived: public Base {
    public:
        Derived() {
            cout<<"Creating derived."<<endl;
        }
    
        ~Derived() {
            cout<<"Killing derived."<<endl;
        }
    };
    
    int main() {
        Base *p = new Derived();
        delete p;
        return 0;
    }
    

    在 G++ 4.7.3 上编译(默认优化),我得到了

    Creating base.
    Creating derived.
    Killing base.
    

    注意Killing derived.的缺失

    【讨论】:

    • 据我了解,析构函数只是在对象被程序实际销毁之前进行手动清理的一种手段。所以,如果我错了,请纠正我,但我认为这段代码证明不了。
    • delete both runs the destructor and frees the memory 如果内存是在堆上分配的(就像使用 new 分配内存时一样)。如果没有调用析构函数,我认为可以肯定地说内存也没有被释放。
    • @AnubhavC 我将您的回答进一步深入,并添加了一些应该考虑的点。如果您有兴趣:stackoverflow.com/a/41801254/1971003
    猜你喜欢
    • 2012-02-14
    • 2010-10-07
    • 2020-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-10
    • 2017-04-28
    • 2018-07-31
    相关资源
    最近更新 更多