当前位置:  开发笔记 > 编程语言 > 正文

我怎么能理解这些析构函数?

如何解决《我怎么能理解这些析构函数?》经验,为你挑选了1个好方法。

我对以下C++代码感到困惑(在http://cpp.sh/8bmp上在线运行).它结合了我在课程中学到的几个概念.

#include 
using namespace std;

class A {
    public:
        A() {cout << "A ctor" << endl;}
        virtual ~A() {cout << "A dtor" << endl;}
};

class B: public A {
    public:
        B() {cout << "B ctor" << endl;}
        ~B() {cout << "B dtor" << endl;}
        void foo(){cout << "foo" << endl;}
};

int main(){
    B *b = new B[1];
    b->~B();
    b->foo();
    delete b;
    return 0;
}

输出:

A ctor
B ctor
B dtor
A dtor
foo
A dtor

这是我不明白的:

    foo调用析构函数后为什么可以调用?

    delete调用析构函数后为什么可以调用?

    如果我注释掉delete b;这段代码会泄漏内存吗?

    析构函数A是虚拟的.我认为在子类中重载的虚函数不会被调用.为什么~A()要打电话呢?

    如果我注释掉,b->~B();那么之后B dtor会打印这一行foo.为什么?

    如果我重复b->~B();两次,那么输出是:B dtor\nA dtor\nA dtor.咦?

    如果我切换delete B;,我得到相同的输出delete[] b;.我认为第二个是正确的,因为b是创建的new[],但它并不重要因为我只是将一个实例推B送到堆中.那是对的吗?

我很抱歉问了这么多问题,但这让我很困惑.如果我的个别问题被误导,那么告诉我在理解每个析构函数运行时需要了解的内容.



1> Mats Peterss..:

"未定义的行为"(简称UB)是允许编译器执行任何操作的地方 - 这通常意味着介于"崩溃","给出不正确的结果"和"做你期望的事情"之间.你b->foo()肯定是未定义的,因为它发生在你的b->~B()电话之后,

由于你的foo函数实际上没有使用被析构函数破坏的任何东西,所以调用foo"工作",因为没有任何东西被破坏了.[这绝不是保证 - 它只是起作用,有点像有时在没有看的情况下过马路是好的,有时它不是.取决于它是什么道路,它可能是一个非常糟糕的主意,或者可能在大多数时间都可以工作 - 但是有一个原因让人们说"向左看,向右看,向左看,然后在安全的情况下交叉"(或类似的东西)那)]

调用delete已经被破坏的对象也是UB,所以再次,它是"运作"的纯粹运气(在"不会导致程序崩溃"的意义上).

deletenew []UB 混合或反之亦然 - 再次,编译器[及其相关的运行时]可能会做正确或错误的事情,具体取决于环境和条件.

不要依赖程序中未定义的行为[1].它肯定会回来咬你.C和C++有相当多的UB案例,至少可以理解最常见的案例,例如"破坏后使用","免费使用"等等,并注意这些案例 - 并避免它不惜一切代价!


哈哈"有点像有时候没有看过去过马路就好了,有时候不是这样"......多么类比:)
推荐阅读
放ch养奶牛
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有