2

我刚刚写了一个示例程序来查看删除这个的行为

class A
 {
   ~A() {cout << "In destructor \n ";}
 public: 
    int a;
    A() {cout << "In constructor \n ";}

    void fun()
     {
       cout << "In fun \n";
       delete this;
       cout << this->a << "\n"; // output is 0
       this->fun_2(); // how m able to call fun_2, if delete this is called first ??
     }

   void fun_2()
    {
      cout << "In fun_2 \n";
    }

main()
{
 A *ptr = new A;
 ptr->a = 100;
 ptr->fun(); //delete this will be executed here
 ptr->fun_2(); //how m able to execute fun_2 when this pointer is deleted ??
 cout<< ptr->a << "\n"; //prints 0
 return 0;
}

> Output
In constructor
In fun
In destructor
0
In fun 2
In fun 2
0

问题

  1. 在 fun() 中执行delete this后,如何使用 fun() 中的指针访问 func_2() ?
  2. 现在主要是如何在删除该指针时执行obj->fun_2 ?
  3. 如果我能够在杀死这个对象后访问函数成员,那么为什么数据成员的值为零'0'?

m 使用 linux ubuntu 和 g++ 编译器

4

2 回答 2

9
  1. 您看到的是未定义的行为:它可能会起作用,也可能会崩溃。
  2. 指针指向一个已删除的实例——它是一个悬空指针。
  3. 这也是一种未定义的行为:您可能会看到零或垃圾值。

Eric Lippert在回答有关函数返回后指向局部变量的指针的问题时提供了一个非常好的“酒店房间的桌子抽屉里的书”类比,它在这里同样适用。

于 2012-08-09T16:21:48.907 回答
2

让我们将其与类似的场景进行比较:

A *a= new A();  
func(a);  
delete a;  
func2(a);  

在我的示例中,编译器只是将指针 a 传递给 func 和 func2,它并不关心它是否指向有效对象。因此,如果您调用func2(a)并且 func2 取消引用指针,这是未定义的行为。如果内存被释放回操作系统并且程序不能再访问*a,程序可能会崩溃。通常 delete 保持分配的内存,不会将其传递回操作系统,因此在 delete 后访问 *a 不会给出异常,而只是返回任何值。这可能是 *a 的先前值,但它也可能是任何其他值,具体取决于 delete 的实现并取决于对 new done 之间的其他调用delete aand *a。例如,MSVC 在调试模式下将内存设置为预定义的模式,以便您在访问释放的内存时可以轻松发现。

为什么这与您的问题有关?因为编译器this作为隐藏的隐式参数传递。

于 2012-08-09T16:30:32.187 回答