Should Objects Delete Themselves in C++

Should objects delete themselves in C++?

The problem with this is that you're really creating an implicit coupling between the object and the World class.

If I try to call Update() outside the World class, what happens? I might end up with the object being deleted, and I don't know why. It seems the responsibilities are badly mixed up. This is going to cause problems the moment you use the Fire class in a new situation you hadn't thought of when you wrote this code. What happens if the object should be deleted from more than one place? Perhaps it should be removed both from the world, the current map, and the player's inventory? Your Update function will remove it from the world, and then delete the object, and the next time the map or the inventory tries to access the object, Bad Things Happen.

In general, I'd say it is very unintuitive for an Update() function to delete the object it is updating. I'd also say it's unintuitive for an object to delete itself.
The object should more likely have some kind of way to fire an event saying that it has finished burning, and anyone interested can now act on that. For example by removing it from the world. For deleting it, think in terms of ownership.

Who owns the object? The world? That means the world alone gets to decide when the object dies. That's fine as long as the world's reference to the object is going to outlast an other references to it.
Do you think the object own itself? What does that even mean? The object should be deleted when the object no longer exists? Doesn't make sense.

But if there is no clearly defined single owner, implement shared ownership, for example using a smart pointer implementing reference counting, such as boost::shared_ptr

But having a member function on the object itself, which is hardcoded to remove the object from one specific list, whether or not it exists there, and whether or not it also exists in any other list, and also delete the object itself regardless of which references to it exist, is a bad idea.

Can an object destroy itself?

Yes, it's legal to call delete this from inside a member function. But there's very rarely a good reason to do so (especially if you're writing idiomatic C++ where most memory-management tasks should be delegated to containers, smart pointers, etc.).

And you need to be very careful:

  • the suicide object must have been allocated dynamically via new (not new[]).
  • once an object has committed suicide, it is undefined behaviour for it to do anything that relies on its own existence (it can no longer access its own member variables, call its own virtual functions, etc.).

When are objects deleted? Impact of creating objects c++

Though your terminology is lacking, the code you wrote allocates the objects "on the stack", and so only last as long as your scope.

In fact, you can write it even more concisely:

//Button singlePlayer = Button(4, 5, "Single Player");  // bad, uses the copy constructor
Button singlePlayer(4, 5, "Single Player"); // uses just a constructor call

Anyway an important thing you should be aware of is that since you're using the "stack" to hold your objects, whether or not you're "allocating" or "freeing" them your "RAM usage" will not change. The "stack" in most implementations is a pre-allocated chunk of memory that never expands, it just throws stack overflow exceptions (or your framework equivalent, I think C has a signal for it?) when it fills up. So generally using your "stack" up on objects is a bad idea.

Self delete an object in C++

It's ok to delete this in case no one will use the object after that call. And in case the object was allocated on a heap of course

For example cocos2d-x game engine does so. It uses the same memory management scheme as Objective-C and here is a method of base object:

void CCObject::release(void)
{
CCAssert(m_uReference > 0, "reference count should greater than 0");
--m_uReference;

if (m_uReference == 0)
{
delete this;
}
}

I don't think it's a c++ way of managing memory, but it's possible

Object delete itself from container

I would have am unload queue.

When a thread notices that the connection is down it registers the object (and continer) with the unload queue tides everything up as much as possible then the thred terminates.

A separate thread is then inside the unload queue. Its sole purpose is to monitor the queue. When it sees a new object on the queue, remove it from the container and then destroy it (syncing with the objects thread as required).

What does delete actually do in c++?

Besides calling the destructor, the delete operator deallocates the memory that was previously allocated by new. This memory goes back to the available pool of memory that can be allocated.

This also means that object now points to invalid memory and any attempt to use it, or any other pointer that pointed to it, will invoke undefined behavior. This is probably what is happening in your program.

So your progam most likely has an issue with who "owns" the pointer. You shouldn't be calling delete on a pointer value that is still being used elsewhere in your program.

Can an object erase itself from a standard C++ container?

When you enter your kill, m[1] (from m[1].kill(m, 1);) statement has been fully evaluated as being the foo object you are calling kill on.

Then you do m.erase(i); ending up destroying the current object foo.

As far as you write absolutely no statement using the current object (this) before you return from the kill function, that's perfectly acceptable and safe (as commented by the posts referenced by Auriga and Barry). Even if the current object does not exist anymore, your function will return safely from the stack, no reason for it to fail as far as I know.

As an illustration, this would end up with undefined behaviour and must NOT BE DONE:

struct foo
{
void kill(std::map<int, foo>& m, int i)
{
m.erase(i);
cout << attribute; // don't do that! current foo object does not exist anymore
}
int attribute;
};

So let's say what you are doing is risky, but valid and safe if you do it well.

As an illustration, this would end up with defined behaviour and CAN BE DONE:

struct foo
{
void kill(std::map<int, foo>& m, int i)
{
int theAttribute = attribute;
m.erase(i);
cout << theAttribute; // OK!
}
int attribute;
};

Having a method delete the current object is probably not a good practice anyway (specially if another developer modifies the code later...he could easily make it crash with the first example above). At least put an explicit comment in the code to tell the current object could have been destroyed (note that kill could destroy the current object, another one, or none...depending on m content and i):

struct foo
{
void kill(std::map<int, foo>& m, int i)
{
m.erase(i);
// careful! current object could have been destroyed by above statement and may not be valid anymore! Don't use it anymore!
}
};

Is it possible for instance to destroy/delete self?

Your question is very interesting, and I don't know of any other way to do so in C# but to force from the inside of the instance its destruction from the outside. So this is what I came up with to check if it is possible.
You can create the class Foo, which has event that is fired when the specific interval of the timer elapses. The class that is registered to that event (Bar) within event de-registers the event and sets the reference of the instance to null. This is how I would do it, tested and it works.

public class Foo
{
public delegate void SelfDestroyer(object sender, EventArgs ea);

public event SelfDestroyer DestroyMe;

Timer t;

public Foo()
{
t = new Timer();
t.Interval = 2000;
t.Tick += t_Tick;
t.Start();
}

void t_Tick(object sender, EventArgs e)
{
OnDestroyMe();
}

public void OnDestroyMe()
{
SelfDestroyer temp = DestroyMe;
if (temp != null)
{
temp(this, new EventArgs());
}
}
}

public class Bar
{
Foo foo;
public Bar()
{
foo = new Foo();
foo.DestroyMe += foo_DestroyMe;
}

void foo_DestroyMe(object sender, EventArgs ea)
{
foo.DestroyMe -= foo_DestroyMe;
foo = null;
}
}

And in order to test this, you can set up a button click within a Form, something like this, and check it in the debugger:

Bar bar = null;
private void button2_Click(object sender, EventArgs e)
{
if(bar==null)
bar = new Bar();
}

So next time when you click the button, you will be able to see that Bar instance still exists but the Foo instance within it is null although it has been created within the Bar's constructor.

Deleting objects in C++ explicitly

You don't have to delete them explicitly, because as you have created them myclass obj; they are created on stack and deleted after each iteration.

When the program reaches the first curly brace after the instantiation on stack of an object it deletes it, in your case:

myclass obj;
obj.do_function();
} // Here the obj is deleted

Here are some examples and explanations of how stack is working, versus heap, to let you understand better when you need to free memory yourself, and when you don't.

Note: I have used notions of stack and heap only to suggest how objects are handled relatively to their lifetime like when an object from stack should be freed after it leaves the scope, and an object of heap lives until it's explicitly freed. As mentioned in comments, these notions are not considered in standard C++ because the programs can run in an environment which does not support these type of memory. Although the compiler respects these rules for a C++ program.



Related Topics



Leave a reply



Submit