11

I have a Thread class like bellow

class Thread {
public:
  Thread();
  ~Thread();
  void start();
  void stop();
}

So i need to call destructor from stop() method, is it a good way to do that?

Mohsen Zahraee
  • 3,309
  • 5
  • 31
  • 45
  • 4
    No, what would happen when the object's lifetime came to an end? It might be better to describe what you need (technically there are corner cases when it might work, but do you want to limit your class to work only in those corner cases?) – juanchopanza Nov 27 '13 at 07:46
  • You can `delete this;` it (if it's a stack var), but it's very risky. Why you want that? Can't you `delete` the object after calling `stop` or use some smart pointer? Or just stack variable? – Kiril Kirov Nov 27 '13 at 07:49
  • @KirilKirov: On which stack would a `Thread` be? Not on its own stack, and not on the stack of some other thread, presumably. – MSalters Nov 27 '13 at 07:51
  • 2
    @MSalters A thread is in no way different from any other class on this behalf. – πάντα ῥεῖ Nov 27 '13 at 07:53
  • @MSalters - kind of on both stacks. The user can create object `Thread` (on it's "own" stack) and then `start` will actually create the OS specific thread (which will internally create a thread-specific stack, but it doesn't matter). The thread may operate safely over all private data members and not only, if additionally synchronized. Am I missing something? – Kiril Kirov Nov 27 '13 at 07:54
  • Related: https://stackoverflow.com/questions/3150942/is-delete-this-allowed-in-c – Gabriel Devillers May 17 '23 at 13:14

6 Answers6

9

Technically yes, but be careful, you should not use the deleted object, this and non-static members anymore:

delete this;

You can also call the destructor:

~Thread();

However, in a well designed code, you can avoid these types of self destructions.

masoud
  • 55,379
  • 16
  • 141
  • 208
  • 1
    +1, You might want to add, not to use `this` or any non-static member variable after the delete statement. – benipalj Nov 27 '13 at 07:48
  • @CommanderCorianderSalamander: The question implies that the destructor must be explicitly called, i.e. it's not called because the object goes out of scope. – MSalters Nov 27 '13 at 07:49
  • 4
    You cant use delete this, if there is any chance the object might be on the stack. But,sometime there are objects that are never and can never be only the stack. I think this topic is in the C++ FAQ – RichardPlunkett Nov 27 '13 at 07:58
  • 1
    Deleting yourself is a very tenuous position to be in (even when valid). Delegate deletion to a management object so that you don't accidentally use any part of yourself after deletion. – Martin York Nov 27 '13 at 08:11
5

Er'body saying don't call delete this from within a member function but to notify the owner that the object is ready to be deleted.

I have a service that creates workers but doesn't care about them after they're created.

From within the service class:

Worker* w;
[...]
while (1) {
  [...]
  w = new Worker();
  [...]
}

Then from within the worker class:

void Worker::doWork() {
  [...]
  [...]
  delete this;
}

All the service class does is make new workers, so outside of the worker class there are no references to the worker except the pointer w which is discarded every time a new worker is created.

In this case i think it makes sense to call delete this inside the worker when it has no more work to do (as long as delete this; is the last statement in doWork() and there are no succesive member calls after doWork().

If you were storing every instance of created worker however, this wouldn't be true anymore.

gwinilts
  • 51
  • 1
  • 1
2

You can use this syntax:

~Thread();

But I doubt if you really need this feature of C++. Maybe you should better design your class.

One legal case for explicitly calling destructors is in custom memory managers which you cannot use the delete operator to delete the object.

Xiangyan Sun
  • 453
  • 4
  • 11
  • 1
    Correct syntax, solid advice. You so very rarely wants to initiate a destruction of yourself like that, that people wanting to is almost always a case of wanting the wrong thing. – RichardPlunkett Nov 27 '13 at 07:56
  • 1
    @RichardPlunkett outside of placement-new object management, I'm hard pressed to think of a reason anyone *would* want to do this. – WhozCraig Nov 27 '13 at 08:03
  • @WhozCraig Agree. In C++ specification §12.4.14: "explicit calls of destructors are rarely needed. One use of such calls is for objects placed at specific addresses using a new-expression with the placement option. Such use of explicit placement and destruction of objects can be necessary to cope with dedicated hardware resources and for writing memory management facilities." – Xiangyan Sun Nov 27 '13 at 08:05
  • @XiangyanSun I feel in good company then, because that (a placement-new situation) is the *only* time i've ever needed to do so, and I've *never* had to manually invoke it *from member function code*. – WhozCraig Nov 27 '13 at 08:06
  • 1
    @WhozCraig: One other situation which is even more rare than placement new management. Is destroying (explicitly calling destructor) then re-creating the object (explicitly using placement new on the old object location). Seen it done never used it but it is legal to do so (as long as object is not accessed between destruction and re-creation). – Martin York Nov 27 '13 at 08:08
  • @LokiAstari Ok, i admit I had to do that as an absolutely dreadful hold-my-nose work-around for a piece of code at work once where outstanding pointers sprinkled throughout various contexts of the code could not be changed, but the object had to be "replaced". The stench drove me from the room. thanks for reminding me of that painful day =P – WhozCraig Nov 27 '13 at 08:11
1

No.

I think that it is bad practice to call destructor from inside the class code. If you need to do cleanup that is done also in the destructor you should use a cleanup() function to encapsulate that work, and have that function called from stop and from the destructor if relevant.

Obviously such a solution would require keeping the state of the object to know if it was already cleaned up or not, to avoid unneeded work and multiple freeing of resources which might no be yours anymore.

Specifically for your case, I'm not sure why you would want to delete the thread from the stop function, if there is some mechanism managing the threads - it should allocate/deallocate the threads from outside, and not the thread itself which deallocates its own memory when stopping. (The thread should perform cleanup as mentioned above, but no force a call to its own destructor)

Max Shifrin
  • 809
  • 9
  • 24
  • Even if the `cleanup()` is exactly the same as the destructor? e.g. I have some mutex to clean up, the destructor (and `cleanup()`, the same), just try to detect which mutex is owned by current thread and unlock it. At some point I want to do `cleanup()`, but when the class instance is destroyed, I want the mutex to be unlocked. So they share exactly the same code. – Robin Hsu Nov 24 '15 at 09:09
1

No. Don't do this.

Have the thread owned by another object.

When you call stop() the thread should tell its owner that it is ready to be deleted (make sure you lock yourself so the owner does not delete before you are finished). Then let the owner of the object do the clean up as appropriate (hopefully in the near future).

Martin York
  • 257,169
  • 86
  • 333
  • 562
  • Could the downvoter enlighten the rest of us? This seems like perfectly reasonable advice for me, which is likely to lead to better code in the majority of cases. – underscore_d Oct 24 '17 at 17:51
0

yes you can. that feature is used in COM as each object have a release function which decrement a private integer of reference count and if it reaches zero it delete the entire object