Related
Is it allowed to delete this; if the delete-statement is the last statement that will be executed on that instance of the class? Of course I'm sure that the object represented by the this-pointer is newly-created.
I'm thinking about something like this:
void SomeModule::doStuff()
{
// in the controller, "this" object of SomeModule is the "current module"
// now, if I want to switch over to a new Module, eg:
controller->setWorkingModule(new OtherModule());
// since the new "OtherModule" object will take the lead,
// I want to get rid of this "SomeModule" object:
delete this;
}
Can I do this?
The C++ FAQ Lite has a entry specifically for this
https://isocpp.org/wiki/faq/freestore-mgmt#delete-this
I think this quote sums it up nicely
As long as you're careful, it's OK for an object to commit suicide (delete this).
Yes, delete this; has defined results, as long as (as you've noted) you assure the object was allocated dynamically, and (of course) never attempt to use the object after it's destroyed. Over the years, many questions have been asked about what the standard says specifically about delete this;, as opposed to deleting some other pointer. The answer to that is fairly short and simple: it doesn't say much of anything. It just says that delete's operand must be an expression that designates a pointer to an object, or an array of objects. It goes into quite a bit of detail about things like how it figures out what (if any) deallocation function to call to release the memory, but the entire section on delete (§[expr.delete]) doesn't mention delete this; specifically at all. The section on destructors does mention delete this in one place (§[class.dtor]/13):
At the point of definition of a virtual destructor (including an implicit definition (15.8)), the non-array deallocation function is determined as if for the expression delete this appearing in a non-virtual destructor of the destructor’s class (see 8.3.5).
That tends to support the idea that the standard considers delete this; to be valid -- if it was invalid, its type wouldn't be meaningful. That's the only place the standard mentions delete this; at all, as far as I know.
Anyway, some consider delete this a nasty hack, and tell anybody who will listen that it should be avoided. One commonly cited problem is the difficulty of ensuring that objects of the class are only ever allocated dynamically. Others consider it a perfectly reasonable idiom, and use it all the time. Personally, I'm somewhere in the middle: I rarely use it, but don't hesitate to do so when it seems to be the right tool for the job.
The primary time you use this technique is with an object that has a life that's almost entirely its own. One example James Kanze has cited was a billing/tracking system he worked on for a phone company. When you start to make a phone call, something takes note of that and creates a phone_call object. From that point onward, the phone_call object handles the details of the phone call (making a connection when you dial, adding an entry to the database to say when the call started, possibly connect more people if you do a conference call, etc.) When the last people on the call hang up, the phone_call object does its final book-keeping (e.g., adds an entry to the database to say when you hung up, so they can compute how long your call was) and then destroys itself. The lifetime of the phone_call object is based on when the first person starts the call and when the last people leave the call -- from the viewpoint of the rest of the system, it's basically entirely arbitrary, so you can't tie it to any lexical scope in the code, or anything on that order.
For anybody who might care about how dependable this kind of coding can be: if you make a phone call to, from, or through almost any part of Europe, there's a pretty good chance that it's being handled (at least in part) by code that does exactly this.
If it scares you, there's a perfectly legal hack:
void myclass::delete_me()
{
std::unique_ptr<myclass> bye_bye(this);
}
I think delete this is idiomatic C++ though, and I only present this as a curiosity.
There is a case where this construct is actually useful - you can delete the object after throwing an exception that needs member data from the object. The object remains valid until after the throw takes place.
void myclass::throw_error()
{
std::unique_ptr<myclass> bye_bye(this);
throw std::runtime_exception(this->error_msg);
}
Note: if you're using a compiler older than C++11 you can use std::auto_ptr instead of std::unique_ptr, it will do the same thing.
One of the reasons that C++ was designed was to make it easy to reuse code. In general, C++ should be written so that it works whether the class is instantiated on the heap, in an array, or on the stack. "Delete this" is a very bad coding practice because it will only work if a single instance is defined on the heap; and there had better not be another delete statement, which is typically used by most developers to clean up the heap. Doing this also assumes that no maintenance programmer in the future will cure a falsely perceived memory leak by adding a delete statement.
Even if you know in advance that your current plan is to only allocate a single instance on the heap, what if some happy-go-lucky developer comes along in the future and decides to create an instance on the stack? Or, what if he cuts and pastes certain portions of the class to a new class that he intends to use on the stack? When the code reaches "delete this" it will go off and delete it, but then when the object goes out of scope, it will call the destructor. The destructor will then try to delete it again and then you are hosed. In the past, doing something like this would screw up not only the program but the operating system and the computer would need to be rebooted. In any case, this is highly NOT recommended and should almost always be avoided. I would have to be desperate, seriously plastered, or really hate the company I worked for to write code that did this.
It is allowed (just do not use the object after that), but I wouldn't write such code on practice. I think that delete this should appear only in functions that called release or Release and looks like: void release() { ref--; if (ref<1) delete this; }.
Well, in Component Object Model (COM) delete this construction can be a part of Release method that is called whenever you want to release aquisited object:
void IMyInterface::Release()
{
--instanceCount;
if(instanceCount == 0)
delete this;
}
This is the core idiom for reference-counted objects.
Reference-counting is a strong form of deterministic garbage collection- it ensures objects manage their OWN lifetime instead of relying on 'smart' pointers, etc. to do it for them. The underlying object is only ever accessed via "Reference" smart pointers, designed so that the pointers increment and decrement a member integer (the reference count) in the actual object.
When the last reference drops off the stack or is deleted, the reference count will go to zero. Your object's default behavior will then be a call to "delete this" to garbage collect- the libraries I write provide a protected virtual "CountIsZero" call in the base class so that you can override this behavior for things like caching.
The key to making this safe is not allowing users access to the CONSTRUCTOR of the object in question (make it protected), but instead making them call some static member- the FACTORY- like "static Reference CreateT(...)". That way you KNOW for sure that they're always built with ordinary "new" and that no raw pointer is ever available, so "delete this" won't ever blow up.
You can do so. However, you can't assign to this. Thus the reason you state for doing this, "I want to change the view," seems very questionable. The better method, in my opinion, would be for the object that holds the view to replace that view.
Of course, you're using RAII objects and so you don't actually need to call delete at all...right?
This is an old, answered, question, but #Alexandre asked "Why would anyone want to do this?", and I thought that I might provide an example usage that I am considering this afternoon.
Legacy code. Uses naked pointers Obj*obj with a delete obj at the end.
Unfortunately I need sometimes, not often, to keep the object alive longer.
I am considering making it a reference counted smart pointer. But there would be lots of code to change, if I was to use ref_cnt_ptr<Obj> everywhere. And if you mix naked Obj* and ref_cnt_ptr, you can get the object implicitly deleted when the last ref_cnt_ptr goes away, even though there are Obj* still alive.
So I am thinking about creating an explicit_delete_ref_cnt_ptr. I.e. a reference counted pointer where the delete is only done in an explicit delete routine. Using it in the one place where the existing code knows the lifetime of the object, as well as in my new code that keeps the object alive longer.
Incrementing and decrementing the reference count as explicit_delete_ref_cnt_ptr get manipulated.
But NOT freeing when the reference count is seen to be zero in the explicit_delete_ref_cnt_ptr destructor.
Only freeing when the reference count is seen to be zero in an explicit delete-like operation. E.g. in something like:
template<typename T> class explicit_delete_ref_cnt_ptr {
private:
T* ptr;
int rc;
...
public:
void delete_if_rc0() {
if( this->ptr ) {
this->rc--;
if( this->rc == 0 ) {
delete this->ptr;
}
this->ptr = 0;
}
}
};
OK, something like that. It's a bit unusual to have a reference counted pointer type not automatically delete the object pointed to in the rc'ed ptr destructor. But it seems like this might make mixing naked pointers and rc'ed pointers a bit safer.
But so far no need for delete this.
But then it occurred to me: if the object pointed to, the pointee, knows that it is being reference counted, e.g. if the count is inside the object (or in some other table), then the routine delete_if_rc0 could be a method of the pointee object, not the (smart) pointer.
class Pointee {
private:
int rc;
...
public:
void delete_if_rc0() {
this->rc--;
if( this->rc == 0 ) {
delete this;
}
}
}
};
Actually, it doesn't need to be a member method at all, but could be a free function:
map<void*,int> keepalive_map;
template<typename T>
void delete_if_rc0(T*ptr) {
void* tptr = (void*)ptr;
if( keepalive_map[tptr] == 1 ) {
delete ptr;
}
};
(BTW, I know the code is not quite right - it becomes less readable if I add all the details, so I am leaving it like this.)
Delete this is legal as long as object is in heap.
You would need to require object to be heap only.
The only way to do that is to make the destructor protected - this way delete may be called ONLY from class , so you would need a method that would ensure deletion
Is it allowed to delete this; if the delete-statement is the last statement that will be executed on that instance of the class? Of course I'm sure that the object represented by the this-pointer is newly-created.
I'm thinking about something like this:
void SomeModule::doStuff()
{
// in the controller, "this" object of SomeModule is the "current module"
// now, if I want to switch over to a new Module, eg:
controller->setWorkingModule(new OtherModule());
// since the new "OtherModule" object will take the lead,
// I want to get rid of this "SomeModule" object:
delete this;
}
Can I do this?
The C++ FAQ Lite has a entry specifically for this
https://isocpp.org/wiki/faq/freestore-mgmt#delete-this
I think this quote sums it up nicely
As long as you're careful, it's OK for an object to commit suicide (delete this).
Yes, delete this; has defined results, as long as (as you've noted) you assure the object was allocated dynamically, and (of course) never attempt to use the object after it's destroyed. Over the years, many questions have been asked about what the standard says specifically about delete this;, as opposed to deleting some other pointer. The answer to that is fairly short and simple: it doesn't say much of anything. It just says that delete's operand must be an expression that designates a pointer to an object, or an array of objects. It goes into quite a bit of detail about things like how it figures out what (if any) deallocation function to call to release the memory, but the entire section on delete (§[expr.delete]) doesn't mention delete this; specifically at all. The section on destructors does mention delete this in one place (§[class.dtor]/13):
At the point of definition of a virtual destructor (including an implicit definition (15.8)), the non-array deallocation function is determined as if for the expression delete this appearing in a non-virtual destructor of the destructor’s class (see 8.3.5).
That tends to support the idea that the standard considers delete this; to be valid -- if it was invalid, its type wouldn't be meaningful. That's the only place the standard mentions delete this; at all, as far as I know.
Anyway, some consider delete this a nasty hack, and tell anybody who will listen that it should be avoided. One commonly cited problem is the difficulty of ensuring that objects of the class are only ever allocated dynamically. Others consider it a perfectly reasonable idiom, and use it all the time. Personally, I'm somewhere in the middle: I rarely use it, but don't hesitate to do so when it seems to be the right tool for the job.
The primary time you use this technique is with an object that has a life that's almost entirely its own. One example James Kanze has cited was a billing/tracking system he worked on for a phone company. When you start to make a phone call, something takes note of that and creates a phone_call object. From that point onward, the phone_call object handles the details of the phone call (making a connection when you dial, adding an entry to the database to say when the call started, possibly connect more people if you do a conference call, etc.) When the last people on the call hang up, the phone_call object does its final book-keeping (e.g., adds an entry to the database to say when you hung up, so they can compute how long your call was) and then destroys itself. The lifetime of the phone_call object is based on when the first person starts the call and when the last people leave the call -- from the viewpoint of the rest of the system, it's basically entirely arbitrary, so you can't tie it to any lexical scope in the code, or anything on that order.
For anybody who might care about how dependable this kind of coding can be: if you make a phone call to, from, or through almost any part of Europe, there's a pretty good chance that it's being handled (at least in part) by code that does exactly this.
If it scares you, there's a perfectly legal hack:
void myclass::delete_me()
{
std::unique_ptr<myclass> bye_bye(this);
}
I think delete this is idiomatic C++ though, and I only present this as a curiosity.
There is a case where this construct is actually useful - you can delete the object after throwing an exception that needs member data from the object. The object remains valid until after the throw takes place.
void myclass::throw_error()
{
std::unique_ptr<myclass> bye_bye(this);
throw std::runtime_exception(this->error_msg);
}
Note: if you're using a compiler older than C++11 you can use std::auto_ptr instead of std::unique_ptr, it will do the same thing.
One of the reasons that C++ was designed was to make it easy to reuse code. In general, C++ should be written so that it works whether the class is instantiated on the heap, in an array, or on the stack. "Delete this" is a very bad coding practice because it will only work if a single instance is defined on the heap; and there had better not be another delete statement, which is typically used by most developers to clean up the heap. Doing this also assumes that no maintenance programmer in the future will cure a falsely perceived memory leak by adding a delete statement.
Even if you know in advance that your current plan is to only allocate a single instance on the heap, what if some happy-go-lucky developer comes along in the future and decides to create an instance on the stack? Or, what if he cuts and pastes certain portions of the class to a new class that he intends to use on the stack? When the code reaches "delete this" it will go off and delete it, but then when the object goes out of scope, it will call the destructor. The destructor will then try to delete it again and then you are hosed. In the past, doing something like this would screw up not only the program but the operating system and the computer would need to be rebooted. In any case, this is highly NOT recommended and should almost always be avoided. I would have to be desperate, seriously plastered, or really hate the company I worked for to write code that did this.
It is allowed (just do not use the object after that), but I wouldn't write such code on practice. I think that delete this should appear only in functions that called release or Release and looks like: void release() { ref--; if (ref<1) delete this; }.
Well, in Component Object Model (COM) delete this construction can be a part of Release method that is called whenever you want to release aquisited object:
void IMyInterface::Release()
{
--instanceCount;
if(instanceCount == 0)
delete this;
}
This is the core idiom for reference-counted objects.
Reference-counting is a strong form of deterministic garbage collection- it ensures objects manage their OWN lifetime instead of relying on 'smart' pointers, etc. to do it for them. The underlying object is only ever accessed via "Reference" smart pointers, designed so that the pointers increment and decrement a member integer (the reference count) in the actual object.
When the last reference drops off the stack or is deleted, the reference count will go to zero. Your object's default behavior will then be a call to "delete this" to garbage collect- the libraries I write provide a protected virtual "CountIsZero" call in the base class so that you can override this behavior for things like caching.
The key to making this safe is not allowing users access to the CONSTRUCTOR of the object in question (make it protected), but instead making them call some static member- the FACTORY- like "static Reference CreateT(...)". That way you KNOW for sure that they're always built with ordinary "new" and that no raw pointer is ever available, so "delete this" won't ever blow up.
You can do so. However, you can't assign to this. Thus the reason you state for doing this, "I want to change the view," seems very questionable. The better method, in my opinion, would be for the object that holds the view to replace that view.
Of course, you're using RAII objects and so you don't actually need to call delete at all...right?
This is an old, answered, question, but #Alexandre asked "Why would anyone want to do this?", and I thought that I might provide an example usage that I am considering this afternoon.
Legacy code. Uses naked pointers Obj*obj with a delete obj at the end.
Unfortunately I need sometimes, not often, to keep the object alive longer.
I am considering making it a reference counted smart pointer. But there would be lots of code to change, if I was to use ref_cnt_ptr<Obj> everywhere. And if you mix naked Obj* and ref_cnt_ptr, you can get the object implicitly deleted when the last ref_cnt_ptr goes away, even though there are Obj* still alive.
So I am thinking about creating an explicit_delete_ref_cnt_ptr. I.e. a reference counted pointer where the delete is only done in an explicit delete routine. Using it in the one place where the existing code knows the lifetime of the object, as well as in my new code that keeps the object alive longer.
Incrementing and decrementing the reference count as explicit_delete_ref_cnt_ptr get manipulated.
But NOT freeing when the reference count is seen to be zero in the explicit_delete_ref_cnt_ptr destructor.
Only freeing when the reference count is seen to be zero in an explicit delete-like operation. E.g. in something like:
template<typename T> class explicit_delete_ref_cnt_ptr {
private:
T* ptr;
int rc;
...
public:
void delete_if_rc0() {
if( this->ptr ) {
this->rc--;
if( this->rc == 0 ) {
delete this->ptr;
}
this->ptr = 0;
}
}
};
OK, something like that. It's a bit unusual to have a reference counted pointer type not automatically delete the object pointed to in the rc'ed ptr destructor. But it seems like this might make mixing naked pointers and rc'ed pointers a bit safer.
But so far no need for delete this.
But then it occurred to me: if the object pointed to, the pointee, knows that it is being reference counted, e.g. if the count is inside the object (or in some other table), then the routine delete_if_rc0 could be a method of the pointee object, not the (smart) pointer.
class Pointee {
private:
int rc;
...
public:
void delete_if_rc0() {
this->rc--;
if( this->rc == 0 ) {
delete this;
}
}
}
};
Actually, it doesn't need to be a member method at all, but could be a free function:
map<void*,int> keepalive_map;
template<typename T>
void delete_if_rc0(T*ptr) {
void* tptr = (void*)ptr;
if( keepalive_map[tptr] == 1 ) {
delete ptr;
}
};
(BTW, I know the code is not quite right - it becomes less readable if I add all the details, so I am leaving it like this.)
Delete this is legal as long as object is in heap.
You would need to require object to be heap only.
The only way to do that is to make the destructor protected - this way delete may be called ONLY from class , so you would need a method that would ensure deletion
The code below should print two same integers, but that's not the case. An analogous program in JavaScript would print two same numbers.
It seems reasonable in C++, because when the stdfun is executed, regfun already finished, the local_var doesn't exist anymore at that time.
So my question is how can we correctly access the captured local variable beyond the lifetime of its context like JavaScript does per default?
#include <functional>
#include <future>
#include <cmath>
#include <iostream>
#include <ctime>
#include <windows.h>
using namespace std;
int start_stdfun_in_a_new_thread(std::function<void()> stdfun)
{
int id = rand();
std::function<void()> call = [=]()
{
Sleep(1000);//let regfun finish
stdfun();
};
std::async(std::launch::async,call);
return id;
}
void regfun()
{
int local_var = -1;
std::function<void()> stdfun = [=,&local_var]() mutable -> void
{
cout<<local_var<<endl;
};
local_var = start_stdfun_in_a_new_thread(stdfun);
cout<<local_var<<endl;
}
int main()
{
regfun();
Sleep(1000000);
}
It is so hard to describe what my question really is, but I just need something in c++ like what we do in javascript. If you are very famillar with javascript, maybe you can understand what I fully mean.
Your local_var is bound to the local context, i.e. it's dead when regfun exits, which happens almost immediately. But your lambda captures it by reference, which means that's a dangling reference when executing stdfun later, since by then local_var is already dead.
So that's undefined behavior. What you would need (what JavaScript does) is extending the lifetime of a captured variable. But that's not the case with C++11 lambdas, as explained in http://en.cppreference.com/w/cpp/language/lambda:
Dangling references
If an entity is captured by reference, implicitly or explicitly, and the function call operator of the closure object is invoked after the entity's lifetime has ended, undefined behavior occurs. The C++ closures do not extend the lifetimes of the captured references.
I see two solutions:
One solution would be heap allocation of the object you want to capture, pointing to it with a std::shared_ptr, and capture this pointer by value (which will copy it into the lambda instance). The last shared pointer instance will then delete the heap allocated object for you.
If possible you can also define it locally in some other context outside which in every case outlives the lifetime of its usage. (In your simple code that would be main, but in the most cases you want to wait for the threads; the context which both starts and waits for the threads is most probably the correct context for this.) Then pass this to regfun by reference, and also capture it by reference. So even when regfun exits, it is still a valid reference (if it's in an outliving context).
Here is a C++ version of your code that no longer does undefined behavior.
As a happy side effect, it also exhibits the behavior you want:
int start_stdfun_in_a_new_thread(std::function<void()> stdfun)
{
int id = rand();
// no need for this to be a type erased `std::function`:
auto call = [=]()
{
Sleep(1000);//let regfun finish
stdfun();
};
std::async(std::launch::async,call);
return id;
}
void regfun()
{
// here we create a shared pointer to an int and store it locally:
auto local_var = std::make_shared<int>(-1);
// we take the shared pointer and copy it by value into our lambda:
// note that we only type erase (turn it into a std::function) when we need to,
// no earlier.
auto stdfun = [local_var]() mutable -> void
{
cout<<*local_var<<endl;
};
// the move is just an optimization. It works with or without it.
*local_var = start_stdfun_in_a_new_thread(std::move(stdfun));
cout<<*local_var<<endl;
}
int main()
{
regfun();
Sleep(1000000);
}
Lifetime of data in C++ is relatively simple, barring a few corner cases1. Variables create their data in automatic storage, and when the variable goes out of scope the data is also recycled. Unnamed data (temporaries) exist for the length of the current statement (until the ;), but under certain circumstances can have their lifetime extended to that of a nearby reference variable. This, however, is not transitory: so under no circumstance do unnamed objects ever outlast the {} enclosed block they are created in.2
You can also create data on the free store via new (or via other methods, like malloc). Such data has a more complicated lifetime, but generally until some code somewhere says "I am done with it" explicitly.
std::shared_ptr is a class used to give your data a more complicated lifetime. You can store data created via new in a std::shared_ptr, but the more conventional way is to use std::make_shared<TYPE>( construction arguments ) to create it (this is, under most circumstances, both safer and more efficient than the other method).
Each std::shared_ptr variable has a conventional lifetime, however the data it points to has a lifetime bounded by the last copy of the shared_ptr that points to it. (I say copy, because this isn't magic: if you have to unrelated shared_ptr to one piece of data, they will (usually) be clueless about their common data, and both think they "own" it).
So you can create a std::shared_ptr<int> and pass it around by value, and the data it points to will live as long as any of the pointers do. When the last pointer goes away, the data is cleaned up.
Which is what I did above. The lifetime of what local_var points to is automatically extended to be both the body of regfun, and the lifetime of stdfun and copies thereof (including the copy that will live in a std::function).
The final technique I used profusely was the use of auto. auto is a way of creating variables that gets it type from how the variable is initialized. For lambdas, this lets you store them directly (instead of as a type-erased std::function), as the name of a lambda cannot be uttered.
In other cases, the right hand side already details the type involved (std::make_shared<int> makes the type clear), and repeating it on the left hand side fails to add much clarity, and violates the DRY (don't repeat yourself) principle.
I use std::function sparingly, as std::function is mainly about type erasure. Type erasure is the act of taking a type with all its details, and wrapping it up in a custom crafted box that erases all of those details and leaves a uniform run time interface. While this is cool and all, it comes with a run time (and sometimes compile time) cost. You should engage in type erasure (like std::function) sparingly: in interfaces where the implementation is hidden, when you want to treat multiple different types (such as function pointers, and multiple different lambdas) in a uniform way and store them, or when you want to use lambdas and would be annoyed by your inability to utter their name.
1 Lifetime of data in C++ is simple, barring a few corner cases. In those corner cases, lifetime can get extremely complex. The most simple of these corner cases is temporary lifetime extension when bound directly to a reference. Other fun corner cases includes the concept of "safely derived pointers" and "strict aliasing", which come into play when you mess around with the types and bits of pointers. Other complex corner cases include static local variables, static and non-static global variables, and thread-local variables, and copy elision2.1. The most basic advice I can give you would be to simply avoid most of these corner cases, and if you find you really really need to use them, spend a whole bunch of time reading up on the implied lifetime and the various common traps and errors that occur. The lifetime issues are sufficiently complex that "I tried it and it worked" is not strong evidence that your code is correct -- undefined, implementation specified, or extremely fragile behavior is ridiculously easy to trigger in all of these cases.
2 This sentence is a lie. 2.1Copy elision can cause an unnamed local variable to have a lifetime far longer than the enclosing block, but only because it conceptually became other named or unnamed variables, and the copy constructor/destructors where all elided (eliminated). However, it is a useful lie, as it helps block thinking about some really common "reference lifetime extension" misconceptions.
I have an object which needs to destroy itself.
Can it be done?
Is the example wrong?
void Pawn::specialMoves(Coordinate const& from, Coordinate const& to, int passant)
{
/*...*/
m_board->replace(to, new Queen(m_colour));//replace pawn by queen
}
void Board::replace(Coordinate const &to, Piece* newPiece)
{
delete tile[to.x()][to.y()];
tile[to.x()][to.y()] = newPiece;
}
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.).
Here's a good sanity check for performing delete this.
Yes, it should work. Even delete this; is allowed.
But the code calling specialMoves() could be in for a nasty surprise.
Q: Can an object destroy itself?
A: Sure. "delete this" is a popular idiom in COM/ActiveX
As far as your algorithm, I'd suggest:
a "board" object has "tiles". Perhaps just a simple 2-D array.
You start out with n "pieces"
Some controller (perhaps a "game" object), moves a "piece" with respect to a "tile".
Each "tile" has a reference to 0 or 1 "pieces"
I'm not sure I see any reason to create or delete anything on a per-move basis.
IMHO...
As long as you don't access member variables or the this pointer after the call to destroy the object, you should be fine. Since it doesn't appear you're doing either of these things, the example should work.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
C++: Delete this?
In C++, is it ok to delete the self object in function definition. What are side effects of this?
class MyClass {
public:
void ~myClass() {}
void myFunction() {
// logic here
delete this;
}
}
Thanks!
From parashift FAQ:
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":
You must be absolutely 100% positively 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).
You must be absolutely 100% positively sure that your member function
will be the last member function invoked on this object.
You must be absolutely 100% positively 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).
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.
You may delete an object from within itself, but it is necessary that you do not, afterward, access any member variables or functions of that class instance after doing so.
It's pretty dangerous. Consider this:
void foo() {
MyClass bar;
bar.myFunction(); // calls delete
} // bar goes out of scope, calls delete again
Check out this C++FAQ 16.15 entry for when doing delete this is possible - it's legal, just needs to be used bery carefully.
The side effects of that are that the object is no longer valid, nor are pointers or references to that object.
I've seen this pattern a lot of places. Typically it's used in a reference counting sort of situation, when the last reference to the object goes away the object deletes itself. It's also typically paired with a factory function of some sort, e.g. a static class member function named Create, taking no parameters, and returning a pointer to the class. The body of this function does the corresponding new, and your constructor can even be private (that way people don't create the object in a way that will mess up your cleanup code).
Depends on your definition of ok!
You can do this, if you are careful, but you shouldn't do it without very good reason, because no-one will be expecting it, and because there is no guarantee that the object has been allocated with new.