删除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;
}
查看程序的输出后,尽管在调用 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
删除只是释放内存(也调用析构函数)。基本上,您使用垃圾
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.我希望此时调用 dev(); ,但这是未定义的行为,因为
this
指针指向已被销毁的对象。您的调用看起来成功的原因是因为您很幸运,并且当您调用dev()
时,没有其他任何东西声明了this
指向的内存,否则,至少可以说,结果将是“有趣的”。I would expect
dev();
to be called at this point but it's undefined behaviour as thethis
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 bythis
when you are callingdev()
, otherwise the results would be "interesting", to say the least.正如您从测试中看到的那样,它可以处理它。
但这是有风险的:例如,如果您修改了 dev 方法来访问 Foo 类的任何实例成员数据,那么您的行为(即在 Foo 实例之后调用 dev 方法)已被删除)将是非法的,并且行为将是未定义的:实际行为将根据程序中其他地方发生的情况而变化,例如 Foo 实例是否占用了内存(以及当 Foo 实例被释放时释放的内存)已被删除)已被另一个线程重新分配。
如果 dev 方法是虚拟方法,并且 Foo 是继承层次结构中的基类或子类,则行为也会有所不同。
如果你将
dev
定义为静态方法会更好:如果你调用一个不能定义为静态的函数(因为它是虚拟的或者因为它访问实例成员数据),那么它是非法的做你正在做的事情。
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 thedev
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: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.
删除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.删除不会删除类的代码或静态变量,只会删除实例变量。然而,正如其他人指出的那样,删除对象指针后使用它所获得的行为是未定义的。
但是问问自己(或者也许问 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.
所有
delete
所做的就是调用析构函数,然后调用operator delete
(内置版本,如果您的类中没有重写)。实际上,它并不比free()
更聪明。没有什么可以阻止您使用已删除的对象。当然,它不会正常工作。调用
delete this;
也相当危险。从那时起,该对象将不再有效,并且如果您尝试调用方法或访问成员,则您将处于未定义操作区域。All
delete
does is call the destructor, thenoperator delete
(the built-in version, if there's no override in your class). It's not any smarter thanfree()
, 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.该对象可能在未定义的时间内仍然可用。此外,
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.