Does explicitly calling destructor result in Undef

2020-02-06 09:00发布

In my opinion, the following code (from some C++ question) should lead to UB, but the it seems it is not. Here is the code:

#include <iostream>
using namespace std;
class some{ public: ~some() { cout<<"some's destructor"<<endl; } };
int main() { some s; s.~some(); }

and the answer is:

some's destructor
some's destructor

I learned form c++ faq lite that we should not explicitly call destructor. I think after the explicitly call to the destructor, the object s should be deleted. The program automatically calls the destructor again when it's finished, it should be UB. However, I tried it on g++, and get the same result as the above answer.

Is it because the class is too simple (no new/delete involved)? Or it's not UB at all in this case?

9条回答
SAY GOODBYE
2楼-- · 2020-02-06 09:26

What the main function does is reserving space on the stack, calling some's constructor, and at the end calling some's destructor. This always happens with a local variable, whatever code you put inside the function. Your compiler won't detect that you manually called the destructor.

Anyway you should never manually call an object's destructor, except for objects created with placement-new.

查看更多
在下西门庆
3楼-- · 2020-02-06 09:28

The behavior is undefined because the destructor is invoked twice for the same object:

  • Once when you invoke it explicitly
  • Once when the scope ends and the automatic variable is destroyed

Invoking the destructor on an object whose lifetime has ended results in undefined behavior per C++03 §12.4/6:

the behavior is undefined if the destructor is invoked for an object whose lifetime has ended

An object's lifetime ends when its destructor is called per §3.8/1:

The lifetime of an object of type T ends when:

— if T is a class type with a non-trivial destructor (12.4), the destructor call starts, or

— the storage which the object occupies is reused or released.

Note that this means if your class has a trivial destructor, the behavior is well-defined because the lifetime of an object of such a type does not end until its storage is released, which for automatic variables does not happen until the end of the function. Of course, I don't know why you would explicitly invoke the destructor if it is trivial.

What is a trivial destructor? §12.4/3 says:

A destructor is trivial if it is an implicitly-declared destructor and if:

— all of the direct base classes of its class have trivial destructors and

— for all of the non-static data members of its class that are of class type (or array thereof), each such class has a trivial destructor.

As others have mentioned, one possible result of undefined behavior is your program appearing to continue running correctly; another possible result is your program crashing. Anything can happen and there are no guarantees whatsoever.

查看更多
不美不萌又怎样
4楼-- · 2020-02-06 09:29

I believe that if you want your code to be OK you simply need to call placement new and fill it back in before exiting. The call to the destructor isn't the issue, it's the second call to the destructor made when you leave scope.

查看更多
登录 后发表回答