Sign in to follow this  

delete this

This topic is 4831 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Basically I am allocating memory as follows:
Object *objs;
objs = new Object[someint];
Now I need to release the memory within the class itself like:
class Object
{
...
void Something()
{
if(whatever)
{
delete this;
}
}
};
If I call delete this within all the dynamically allocated objects will all the memory be perfectly freed again? Also is this bad practice, or even not possible? -CProgrammer

Share this post


Link to post
Share on other sites
It is perfectly fine to delete this as long as you aren't using the object after the delete in your function (or anytime after the function exits). This is actually pretty common when working with objects across DLLs, often times coupled with reference counting. Calling delete on an object not allocated in the same executable is not legal, so you make a virtual function that does the deleting when you call it (that way the object is always deallocated from a function in their own executable). One place you will see this a lot that I'm sure you've worked with is COM interfaces. An extremely common way of implementing Release for a COM interface is to delete this when the interface reference count reaches 0 (so the odds are that all of your directx interfaces have a delete this line in their release functions).

Edit: After rereading I noticed you are attempting to delete elements of a dynamically allocated array individually. Don't do that! Only call delete this if the object itself was dynamically allocated with new.

[Edited by - Polymorphic OOP on September 18, 2004 10:12:00 PM]

Share this post


Link to post
Share on other sites
It is TOTALLY OK, and TOTALLY NORMAL ... but remember, don't ever delete this in any function, in any way, that the client wouldn't be expecting the object to be deleted ... cause the client has no way to check if a pointer is valid or not ...

if a client does this:

YourClass x = new YourClass();
...
x->DoStuff();

// the client must KNNOW, 100% if the x obect has been deleted ...

because first of all, if the client then does

x->DoOtherStuff();

on a deleted object, program should now crash with a seg fault.

second, if client does:

delete x;

on an already deleted object, program should crash also ...

so it is FINE for something like:

x->Release();

to delete this IF the ref count is 0, cause the rules of using the x object are such that NO CLIENT SHOULD be manually deleting x, and also no client should be doing anything to x whatsoever after the Release call ...

so basically - delete this; is only viable inside of functions who's job is to manage the life of the object ...

Share this post


Link to post
Share on other sites
Quote:
Original post by CProgrammer
If I call delete this within all the dynamically allocated objects will all the memory be perfectly freed again?

Yes, it really makes no diference, for instance, the following produce the same result:

// example 1
MyObject *array = MyObject[1024];
delete [] array;
// example 2
MyObject *array = MyObject[1024];
for (unsigned int i = 0; i < 1024; i++)
delete array + i;



And yes, I know c++ purists will complain about that pointer addition, having been recently flamed on the point, but really, is delete &array[ i ] any better?

[edit] At first glance, i thought this topic's title was a request for a moderator to remove the topic ;)[/edit]
SwiftCoder

Share this post


Link to post
Share on other sites
Quote:
Original post by swiftcoder
Quote:
Original post by CProgrammer
If I call delete this within all the dynamically allocated objects will all the memory be perfectly freed again?

Yes, it really makes no diference, for instance, the following produce the same result:
*** Source Snippet Removed ***
And yes, I know c++ purists will complain about that pointer addition, having been recently flamed on the point, but really, is delete &array[ i ] any better?


Nonono!!! Don't EVER do that. Those two examples do NOT do the same thing. In fact, example two is not legal! You can never call delete on the individual elements of a dynamically allocated array and think that it will deallocate the elements individually. You will get undefined results (which will often cause a program crash, or worse, your program won't crash but it will be in an undeterminable state). The ONLY valid way to deallocate a dynamically allocated array in C++ is to call delete [] on the pointer to the first element of the array.

Share this post


Link to post
Share on other sites
CProgrammer, the answer to your question is no. You must delete an allocation the same way you new it. swiftcoder is wrong. His example does not work. If you allocate an array like this:
    Object *objs = new Object[someint]; 
You must delete it like this:
    delete [] objs; 
You cannot do this:
    for ( int i = 0; i < someint; i++ )
{
delete &objs[i];
}
or
for ( int i = 0; i < someint; i++ )
{
objs[i].FunctionThatContainsDeleteThis();
}
If you want to delete indvidual objects in an array, you need an array of pointers like this:
    Object * apObjs[ someint ];
for ( int i = 0; i < someint; i++ )
{
apObjs[i] = new Object;
}
Then you can/must delete the objects like this:
    for ( int i = 0; i < someint; i++ )
{
delete apObjs[i];
}
or
for ( int i = 0; i < someint; i++ )
{
apObjs[i]->FunctionThatContainsDeleteThis();
}


Other than that, delete this is a bad idea if you can't guarantee that the object was allocated with new, and not new[] or on the stack or as a member variable.

Share this post


Link to post
Share on other sites
Actually im using 'delete this' for instances of objects.

Basically an instance is pushed into a quadtree. If the object is to be deleted the quadtree calls a member function including 'delete this'.
By the way does a call to the constructor as
Add(CInstance(...));
count as a 'new' call. Id think so just making sure.

-CProgrammer

Share this post


Link to post
Share on other sites
Quote:
Original post by CProgrammer
Actually im using 'delete this' for instances of objects.
By the way does a call to the constructor as
Add(CInstance(...));
count as a 'new' call. Id think so just making sure.

-CProgrammer


no, that just creates a temporary instance and passes it to the Add function.

Share this post


Link to post
Share on other sites
Quote:
Original post by Polymorphic OOP
Quote:
Original post by CProgrammer
Actually im using 'delete this' for instances of objects.
By the way does a call to the constructor as
Add(CInstance(...));
count as a 'new' call. Id think so just making sure.

-CProgrammer


no, that just creates a temporary instance and passes it to the Add function.


Sorry my mistake.
I meant this:
Add(&CInstance(...));
Does the pointer I receive in the function do have to have its memory released with 'delete'?

At the moment im doing:
CInstance *instance = new CInstance(...);
Add(instance);
But the above way id prefer so im asking wether its any different?

-CProgrammer

Share this post


Link to post
Share on other sites
Quote:
Original post by CProgrammer
Add(&CInstance(...));
Does the pointer I receive in the function do have to have its memory released with 'delete'?
At the moment im doing:
CInstance *instance = new CInstance(...);
Add(instance);
But the above way id prefer so im asking wether its any different?
-CProgrammer


AFAIK new CInstance() allocates enough memory for a CInstance object, and then calls the constructor to initialise the memory, whereas &Cinstance() creates and initialises a temporary variable, and then takes the address of the temporary thus resulting in a bad pointer when the temporary goes out of scope.

Now I have a question:
If I call new CInstance; instead of new CInstance( );
does the constructor still get called?
I assume not, and that new just allocates the memory, but i would like to know for sure.

SwiftCoder

Share this post


Link to post
Share on other sites
Quote:
Original post by swiftcoder
If I call new CInstance; instead of new CInstance( );
does the constructor still get called?
I assume not, and that new just allocates the memory, but i would like to know for sure.

SwiftCoder

The constructor is still called.

Share this post


Link to post
Share on other sites
Quote:
Original post by swiftcoder
If I call new CInstance; instead of new CInstance( );
does the constructor still get called?

It does.
Quote:
I assume not, and that new just allocates the memory, but i would like to know for sure.

You assume wrong - new/delete allways call ctors/dtors if they exist.

alloc/free, on the other hand, have no concept of types built in, and thus have no way of calling ctors/dtors.

Share this post


Link to post
Share on other sites
Just a friendly reminder that bad advice makes your rating decrease and leads others astray, whilst no advice has neither effect.
It is sometimes better to say "I don't know" or not post at all.

Share this post


Link to post
Share on other sites
Quote:
Original post by CProgrammer
I meant this:
Add(&CInstance(...));
Does the pointer I receive in the function do have to have its memory released with 'delete'?

At the moment im doing:
CInstance *instance = new CInstance(...);
Add(instance);
But the above way id prefer so im asking wether its any different?

-CProgrammer


the first will create a dangling pointer (it creates a temp variable on the stack which gets deleted as soon as the function with that code in it ends).

The closest thing to the first one, with the functionality of the 2nd, would be:

Add(new CInstance(...));

which should work just fine (and would need to have it's memory deleted).

Share this post


Link to post
Share on other sites
As always, see the C++ FAQ Lite:

Quote:
Is it legal (and moral) for a member function to say delete this?

As long as you're careful, it's OK for an object to commit suicide (delete this).

Here's how I define "careful":

1) You must be absolutely 100% positive sure that this object was allocated via new (not by new[], nor by placement new, nor a local object on the stack, nor a global, nor a member of another object; but by plain ordinary new).

2) You must be absolutely 100% positive sure that your member function will be the last member function invoked on this object.

3) You must be absolutely 100% positive sure that the rest of your member function (after the delete this line) doesn't touch any piece of this object (including calling any other member functions or touching any data members).

4) You must be absolutely 100% positive sure that no one even touches the this pointer itself after the delete this line. In other words, you must not examine it, compare it with another pointer, compare it with NULL, print it, cast it, do anything with it.

Naturally the usual caveats apply in cases where your this pointer is a pointer to a base class when you don't have a virtual destructor.


edit: I think the main point is that you almost never, ever are in a situation where it's safe to call delete this. The safe situation is well known (and therefore not frightening or open to superstition or dogmatism) but it is unlikely to be a situation you find yourself in.

[Edited by - petewood on September 20, 2004 7:42:26 AM]

Share this post


Link to post
Share on other sites
Sorry, but IME 'delete this' is a code smell. Why not keep it simple? When you need a new object, call new/new[]. When you're done with it, call delete/delete[]. Simple. IMHO there's usually no reason to mess with this straightforward mechanism (unless you're writing something like a "smart pointer" class or something). The main reason not to is that the lifecycle of an object gets obscured. Also, objects can only be created on the heap (beware of arbitrary limitations like that;-). And it can cause all kinds of unnessecary confusion about the validity of a pointer, especially if the class is used by someone who didn't write it.

Share this post


Link to post
Share on other sites
Quote:
Sorry, my bad, i was thinking of Objective-C

Um...I don't think that it works in Objective-C, either, for the same reason that it doesn't work in C++—certain objects may involve more than just allocated memory, such as pipes or sockets, and it's difficult to guarantee otherwise.

Share this post


Link to post
Share on other sites
Quote:
Original post by LNK2001
Sorry, but IME 'delete this' is a code smell. Why not keep it simple? When you need a new object, call new/new[]. When you're done with it, call delete/delete[]. Simple. IMHO there's usually no reason to mess with this straightforward mechanism (unless you're writing something like a "smart pointer" class or something). The main reason not to is that the lifecycle of an object gets obscured. Also, objects can only be created on the heap (beware of arbitrary limitations like that;-). And it can cause all kinds of unnessecary confusion about the validity of a pointer, especially if the class is used by someone who didn't write it.


I can understand your doubts on 'delete this' and I dont feel totally comfortable with it easier.
But if I dont use it I have to keep track of all instances I create and manually delete them.
At the moment its very flexible.
I just push an instance pointer into the quadtree which holds linked lists containing objects. Once the object is to be erassed the quadtree just calls a member function which in turn makes the object delete itself.
If I dont do it this way then how. Should I check the original instance repeatedly and see wether a destroy me flag is set?
If someone knows a better way please tell me.
Would you guys think having a static amount of instances of a type is better. If I want to place one I go through the array until I find an unused one.

Another thing. Will breaking the rules cause a definet crash. If so atleast one knows when a mistake has been made.

-CProgrammer

Share this post


Link to post
Share on other sites

This topic is 4831 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this