2
#include <stdio.h>

class Foo {

        public:
                Foo(char x);
                Foo(char x, int y);
                ~Foo();
                void abc();
                void dev();
};

void Foo::dev()
{

        printf("inside dev \n");
}

void Foo::abc()
{

        printf("inside abc \n");
        delete this;
        dev();
}

Foo::Foo(char x)
{

      printf("inside 1 argu const---------------");

}

Foo::~Foo()
{

    printf("inside 1 argu dest---------------");
}

#include "test.h"

int main()
{

        Foo *obj=new Foo('a');
        printf("%u inside main\n", obj);
        obj->abc();
        return 0;
}

在查看程序的输出之后,似乎仍然调用了“dev”函数,尽管在调用 dev 之前在函数 abc 中调用了“delete this”?gcc/g++ 如何处理这个问题?

4

7 回答 7

12

该对象可能在未定义的时间内仍然可用。此外,delete不会影响有问题的指针。

Delete只需在对象实例上调用析构函数。Delete将内存返回到池中,但关于何时重用该内存(如果有的话)是未定义的(和运行时相关的)。该对象很可能在程序的剩余时间内可用,但重点是:不要指望它

有一个不那么明显的陷阱需要注意:对象无法知道它是否是动态分配的。因此,如果对象是静态分配的调用,delete this则在所述对象上将证明是有问题的。上面的情况并非如此。

于 2010-01-15T13:04:22.793 回答
6

删除只是释放内存(也调用析构函数)。基本上你用垃圾this指针调用 dev ,它只是因为 dev 不是虚拟的并且它不会尝试访问任何成员变量,否则它可能会像使用任何其他无效指针一样访问冲突。

于 2010-01-15T13:06:35.763 回答
2

gcc/g++ 如何处理这个问题?

正如您从测试中看到的那样,它可以处理它。

但是这是有风险的:例如,如果您修改了dev访问 Foo 类的任何实例成员数据的方法,那么您的行为(即dev在 Foo 实例被删除后调用该方法)将是非法的,并且该行为将是未定义的:实际行为会根据程序中其他地方发生的情况而有所不同,例如 Foo 实例占用的内存(以及在 Foo 实例被删除时释放的内存)是否已被另一个线程重新分配。

dev如果方法是虚拟方法,并且 Foo 是继承层次结构中的基类或子类,则行为也会有所不同。

如果您定义dev为静态方法会更好:

class Foo {

public:
    Foo(char x);
    Foo(char x, int y);
    ~Foo();
    void abc();
    static void dev();
};

如果你调用一个不能定义为静态的函数(因为它是虚拟的或者因为它访问实例成员数据),那么你正在做的事情是非法的。

于 2010-01-15T13:08:15.280 回答
1

我希望dev();此时会被调用,但这是未定义的行为,因为this指针指向已被破坏的对象。您的调用似乎成功的原因是因为您很幸运,并且没有其他任何东西占用了this您调用时指向的内存dev(),否则至少可以说结果将是“有趣的”。

于 2010-01-15T13:07:06.953 回答
1

delete this通常不会影响 this 指针本身,所以它仍然可以用来调用函数。这种行为是未定义的——它可能有效,也可能无效。一般来说,delete this在 C++ 中是一个坏主意。使用它的唯一理由是在某些引用计数类中,并且有更好的引用计数方法不需要使用它。

于 2010-01-15T13:07:39.197 回答
1

Delete 不会删除类的代码或静态变量,只会删除实例变量。正如其他人指出的那样,在删除对象指针后使用对象指针的行为是未定义的。

但是问问自己这个(或者也许问 stackoverflow ;-):如果类的实例不存在,你能调用类的静态成员函数吗?(答案是肯定的,当然。)

如果 dev() 是静态的,那么这段代码将是完全合法的。

于 2010-01-15T13:13:54.303 回答
0

delete所做的就是调用析构函数,然后operator delete(内置版本,如果你的类中没有覆盖)。它并不比 聪明free(),真的。没有什么可以阻止您使用已删除的对象。它不会正常工作,当然。

打电话delete this;也很危险。从那时起,该对象将无效,如果您尝试调用方法或访问成员,则您处于未定义操作区域。

于 2010-01-15T13:05:39.343 回答