C++为什么释放内存后还能访问

img

img


/*
运行阶段类型识别,为程序在运行阶段确定对象的类型,只适用于包含虚函数的类
问题引入:基类指针可以指向派生类对象,如何知道基类指针指向的是那个派生类的对象呢?
dynamic_cast运算符使用指向基类的指针来生成派生类指针,它不能回答“指针指向的是什么类的对象”,但能回答“是否可以安全的将对象的地址赋值给特定类型的指针”
这个问题
重点复习:free 和 delete可以一起释放掉后面的连续空间
*/

//以下为虚函数复习,dynamic_cast

#include 
using namespace std;

class Hero
{
public:
    virtual void skill1()
    {
        cout << "英雄释放了1技能" << endl;
    }
    
    virtual void skill2()
    {
        cout << "英雄释放了2技能" << endl;
    }

    virtual void skill3()
    {
        cout << "英雄释放了3技能" << endl;
    }
};

class XS : public Hero
{
public:
    virtual void skill1()
    {
        cout << "西施释放了1技能" << endl;
    }

    virtual void skill2()
    {
        cout << "西施释放了2技能" << endl;
    }

    virtual void skill3()
    {
        cout << "西施释放了3技能" << endl;
    }

    void skill4()
    {
        cout << "西施释放了4技能" << endl;
    }
};

class LB : public Hero
{
public:
    virtual void skill1()
    {
        cout << "李白释放了1技能" << endl;
    }

    virtual void skill2()
    {
        cout << "李白释放了2技能" << endl;
    }

    virtual void skill3()
    {
        cout << "李白释放了3技能" << endl;
    }
};

class HZ : public Hero
{
public:
    virtual void skill1()
    {
        cout << "猴子释放了1技能" << endl;
    }

    virtual void skill2()
    {
        cout << "猴子释放了2技能" << endl;
    }

    virtual void skill3()
    {
        cout << "猴子释放了3技能" << endl;
    }
};

int main()
{
    Hero* ptr = nullptr;
    int id;
    cin >> id;
    switch (id)
    {
    case 1:
        ptr = new XS;
        break;
    case 2:
        ptr = new LB;
        break;
    case 3:
        ptr = new HZ;
        break;
    default:
        ptr = new Hero;
        break;
    }
    ptr->skill1();
    ptr->skill2();
    ptr->skill3();

    if (id == 1)
    {
        XS* xsptr = dynamic_cast(ptr);
        xsptr->skill4();
        delete xsptr;
        //为什么这里释放掉xsptr后还能调用skill4
        xsptr->skill4();
    }
    return 0;
}

应该叫C++为什么释放对象内存后还能访问类成员函数.
*
因为你的对象内存中只存储一个虚函数表指针, 如果有成员对象则还会存储成员对象.
*
delete只是释放虚函数表指针和成员对象, 所以调用成员对象或虚函数会报错, 但delete没有清除类本身的实现, 所以哪怕指向nullptr的类指针也能调用类成员函数. 当然, 如果这个类成员函数调用类成员对象一样会报错.

空间被释放了,只是指针并没有置为空。所以可以访问,只是访问到的值可能不是原来的了.