问题
#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 ?
回答1:
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.
回答2:
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.
回答3:
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.
回答4:
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.
回答5:
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.
回答6:
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.
回答7:
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.
来源:https://stackoverflow.com/questions/2071579/delete-this-pointer-behaviour-in-g