为什么即使在删除对象后我也可以访问成员函数?

San*_*lin 0 c++ function object member delete-operator

我是C++的新手,从我到目前为止学到的东西,当你在一个指向堆上创建的东西的指针上调用delete时,该指针所指向的任何内容都会被擦除并释放内存,对吧?

但是当我在一个简单的类上尝试这个时:

class MyClass
{
    int _Id;
public:
    MyClass(int id) : _Id(id)
    {
        std::cout << "$Constructing the damn thing! " << _Id << std::endl;
    }
    ~MyClass()
    {
        std::cout << "?Destructing the damn thing! " << _Id << std::endl;
    }
    void Go_XXX_Your_Self()
    {
        std::cout << "%OooooooooO NOOOOOO! " << _Id << std::endl;
        delete this;
    }
    void Identify_Your_Self()
    {
        std::cout << "#Object number: " << _Id << " Located at: " << this << std::endl;
    }
};
Run Code Online (Sandbox Code Playgroud)

这些只是一些愚蠢的测试,看看删除如何工作:

int main()
{
    MyClass* MC1 = new MyClass(100);
    MyClass* MC2 = new MyClass(200);
    MyClass* MC3 = MC2;

    std::cout << MC1 << " " << MC2 << " " << MC3 << " " << std::endl;

    MC1->Identify_Your_Self();
    MC2->Identify_Your_Self();
    MC3->Identify_Your_Self();

    delete MC1;

    MC1->Identify_Your_Self();


    MC3->Go_XXX_Your_Self();

    MC3->Identify_Your_Self();


    delete MC2;

    MC2->Identify_Your_Self();

    MC2->Go_XXX_Your_Self();

    MC2->Identify_Your_Self();

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这是输出:

$Constructing the damn thing! 100
$Constructing the damn thing! 200
0x3e3e90 0x3e3eb0 0x3e3eb0
#Object number: 100 Located at: 0x3e3e90
#Object number: 200 Located at: 0x3e3eb0
#Object number: 200 Located at: 0x3e3eb0
?Destructing the damn thing! 100
#Object number: 0 Located at: 0x3e3e90
%OooooooooO NOOOOOO! 200
?Destructing the damn thing! 200
#Object number: 4079248 Located at: 0x3e3eb0
?Destructing the damn thing! 4079248
#Object number: 4079280 Located at: 0x3e3eb0
%OooooooooO NOOOOOO! 4079280
?Destructing the damn thing! 4079280
#Object number: 4079280 Located at: 0x3e3eb0
Run Code Online (Sandbox Code Playgroud)

所以,我的问题是,为什么即使在删除对象后我仍然可以调用Go_XXX_Your_Self()和Identify_Your_Self()?

这是它在C++中的工作原理吗?(甚至在你删除它之后呢?)

还可以检查一下它是否不存在?(我知道理论上是不可能的,但我很想知道那里有什么方法)

Mar*_*cia 8

所以,我的问题是,为什么即使在删除对象后我仍然可以调用Go_XXX_Your_Self()和Identify_Your_Self()?

由于未定义的行为.

这是它在C++中的工作原理吗?(甚至在你删除它之后呢?)

由于未定义的行为.无法保证它在其他实现中的工作方式相同.再次,未定义的行为.

还可以检查一下它是否不存在?(我知道理论上是不可能的,但我很想知道那里有什么方法)

delete MC1;
MC1 = nullptr;
Run Code Online (Sandbox Code Playgroud)

通过将指针设置为nullptrdelete其之后,运行时最有可能检测到您正在访问无效的,您没有权利的位置.此外,通过努力为所有适用的指针执行此操作,您可以检查对象是否有效(如果不是,则有效nullptr).

if(my_ptr) {
   // my_ptr is most possibly valid (though you can still go wrong)
   // use my_ptr
}
Run Code Online (Sandbox Code Playgroud)

同样,您还应该将原始指针设置nullptr为尚未初始化为某个有效地址的时间.

MyClass* some_ptr = nullptr;
...
Run Code Online (Sandbox Code Playgroud)

但同样,如果您可以访问现代C++ 11工具,最好不要使用原始指针,只需使用std::unique_ptrstd::shared_ptr(取决于您所需的语义).在未来的C++标准版本中,您可能还希望使用建议的std::exempt_ptr,这是一个非拥有的,仅观察指针包装器.