为什么即使在对象被删除后也可以访问成员函数? [英] Why I can access member functions even after the object was deleted?

查看:179
本文介绍了为什么即使在对象被删除后也可以访问成员函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是C ++的新手,根据我所学到的,当你对指向堆上创建的某个指针的指针调用delete时,该指针指向的内容被擦除,内存被释放,是吗? p>

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

  class MyClass 
{
int _Id;
public:
MyClass(int id):_Id(id)
{
std :: cout< $构建这个死的东西!< _Id<< std :: endl;
}
〜MyClass()
{
std :: cout< 摧毁那个死的东西!< _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<< 位于:<这个<< std :: endl;
}
};

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

  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();


删除MC2;

MC2-> Identify_Your_Self();

MC2> Go_XXX_Your_Self();

MC2-> Identify_Your_Self();

return 0;
}

这里是输出:

  $构建这个死的东西! 100 
$构建这个死的东西! 200
0x3e3e90 0x3e3eb0 0x3e3eb0
#对象编号:100位于:0x3e3e90
#对象编号:200位于:0x3e3eb0
#对象编号:200位于:0x3e3eb0
?拆毁这个死的东西! 100
#Object number:0位于:0x3e3e90
%OooooooooO NOOOOOO! 200
?毁坏的东西! 200
#对象编号:4079248位于:0x3e3eb0
?毁坏的东西! 4079248
#主题编号:4079280位于:0x3e3eb0
%OooooooooO NOOOOOO! 4079280
?破坏这件事! 4079280
#Object number:4079280位于:0x3e3eb0

即使在对象被删除后,我仍然可以调用Go_XXX_Your_Self()和Identify_Your_Self()?



这是如何在C ++中工作的? (即使在您删除它之后,是否仍然存在?)



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

解决方案


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


由于未定义的行为



< blockquote>

这是如何在C ++中工作的? (即使在您删除它之后仍然存在?)


因为未定义的行为。不能保证它将在其他实现上工作相同。 未定义的行为


也可以检查它是否不在那里? (我理解是不可能的,但我很想知道有什么方法)




  delete MC1; 
MC1 = nullptr;



通过将 nullptr code> delete ,运行时很有可能检测到您正在访问一个无效的,您没有使用权的位置。此外,通过对所有适用的指针执行此操作,您可以检查对象是否有效(如果非 nullptr ,则为有效)。

  if(my_ptr){
// my_ptr最可能有效(尽管你仍然可能出错)
// use类似地,你还应该将原指针设置为
}


$ b <


$ b

  MyClass * some_ptr = nullptr 


...

但是,如果你可以访问现代C ++ 11设施,最好不要使用原始指针,只需使用 std :: unique_ptr std :: shared_ptr (取决于你需要的语义)。在未来的C ++标准版本中,您可能还需要使用提出了 std :: exempt_ptr 这是一个非所有的,仅观察的指针包装器。


I'm new to C++ and from what I learned so far when you call delete on a pointer that points to something created on the heap then whatever is pointed by that pointer gets erased and the memory is freed, right?

However when I tried this on a simple class:

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;
    }
};

These are just some stupid tests to see how delete works:

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;
}

Here's the output:

$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

So, my question is, why I'm still able to call Go_XXX_Your_Self() and Identify_Your_Self() even after the object was deleted?

Is this how it works in C++? (is there even after you delete it?)

Also can you check to see if it's not there? (I know theoretically is not possible but I'm curious to see what methods are out there)

解决方案

So, my question is, why I'm still able to call Go_XXX_Your_Self() and Identify_Your_Self() even after the object was deleted?

Because of undefined behavior.

Is this how it works in C++? (is there even after you delete it?)

Because of undefined behavior. There is no guarantee that it will work the same on other implementations. Again, undefined behavior.

Also can you check to see if it's not there? (I know theoretically is not possible but I'm curious to see what methods are out there)

delete MC1;
MC1 = nullptr;

By setting the pointer to nullptr after deleteing it, the runtime is most likely to detect that you are accessing an invalid, you-have-no-right-to-use location. Also, by diligently doing this for all applicable pointers, you have the ability to check if the object is valid or not (valid if non-nullptr).

if(my_ptr) {
   // my_ptr is most possibly valid (though you can still go wrong)
   // use my_ptr
}

Similarly, you should also set raw pointers to nullptr when they aren't yet initialized to some valid address.

MyClass* some_ptr = nullptr;
...

But again, if you have access to modern C++11 facilities, it's much better not to use raw pointers at all, and just use std::unique_ptr or std::shared_ptr (depending on your required semantics). And on future C++ standard revisions, you may also want to use the proposed std::exempt_ptr which is a non-owning, observe-only pointer wrapper.

这篇关于为什么即使在对象被删除后也可以访问成员函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆