删除g++中的这个指针行为

发布于 2024-08-18 04:00:25 字数 755 浏览 8 评论 0原文

#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 之前在函数 abc 中调用了“delete this”,但“dev”函数似乎仍然被调用? gcc/g++ 如何处理这个问题?

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

After looking at the output of the program, it seems that "dev" function is still invoked despite being "delete this" is called in function abc before invoking dev ? How does gcc/g++ handles this ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

行至春深 2024-08-25 04:00:26

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

Delete just deallocates the memory (calling the destructor as well). Basically you called dev with a trash this pointer, it works only because dev wasn't virtual and it doesn't try to access any member variables, otherwise it would likely access violate just like using any other invalid pointer.

鼻尖触碰 2024-08-25 04:00:26

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

I would expect dev(); to be called at this point but it's undefined behaviour as the this pointer is pointing at an object that has been destroyed. The reason that your call appears to be succeeding is because because you're getting lucky and nothing else has claimed the memory pointed to by this when you are calling dev(), otherwise the results would be "interesting", to say the least.

浊酒尽余欢 2024-08-25 04:00:26

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

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

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

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

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

class Foo {

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

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

How does gcc/g++ handles this ?

It handles it as you can see from your testing.

It's risky though: for example if you modified the dev method to access any instance member data of the Foo class, then your behaviour (i.e. calling the dev method after the Foo instance has been deleted) would be illegal, and the behaviour would be undefined: the actual behaviour would vary depending on what was happening elsewhere in the program, for example on whether the memory which the Foo instance occupied (and which was released when the Foo instance was deleted) has been reallocated by another thread.

The behaviour would also be different if the dev method were a virtual method, and Foo were a base class or a subclass in an inheritance hiearchy.

It would be better if you defined dev as a static method:

class Foo {

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

If you call a function which cannot be defined as static (because it's virtual or because it accesses instance member data), then it would be illegal to do what you were doing.

殊姿 2024-08-25 04:00:26

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

delete this will not normally affect the this pointer itself, so it can still be used to call the function. This behaviour is undefined though - it might work, it might not. In general, delete this is a bad idea in C++. The only justification for using it is in some reference counted classes, and there are beter approaches to reference counting which do not require its use.

咆哮 2024-08-25 04:00:26

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

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

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

Delete doesn't delete the code or static variables of a class, just the instance variables. As other people pointed out, the behavior you get using an object pointer after you delete it is undefined, however.

But ask yourself this (or maybe ask stackoverflow ;-): Can you call a static member function of a class if no instances of the class exist? (The answer is yes, of course.)

If dev() were static, this code would be perfectly legal.

夜深人未静 2024-08-25 04:00:26

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

调用 delete this; 也相当危险。从那时起,该对象将不再有效,并且如果您尝试调用方法或访问成员,则您将处于未定义操作区域。

All delete does is call the destructor, then operator delete (the built-in version, if there's no override in your class). It's not any smarter than free(), really. There's nothing to prevent you from using a deleted object. It won't work right, sure.

Calling delete this; is pretty risky as well. The object won't be valid from that point on, and if you try to call methods or access members, you're in undefined-operation territory.

离旧人 2024-08-25 04:00:25

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

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

有一个不太明显的陷阱需要注意:对象无法知道它是否是动态分配的。因此,如果该对象是静态分配的调用,则在该对象上删除此将会出现问题。但上面的情况并非如此。

The object might be still available for undefined time. Also, delete doesn't affect the pointer in question.

Delete just calls the destructor on the object instance. Delete returns the memory to the pool but it is undefined (and runtime related) as to when this memory will be reused (if at all). The object can very well be available for the rest of the duration of the program but the point is: don't count on it.

There is a not so obvious pitfall to take notice of: the object has no way of knowing if it was allocated dynamically. Hence, if the object was statically allocated calling, delete this on the said object will prove problematic. This isn't the case above though.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文