In C++ the following code gives a compiler error:
void destruct1 (int * item)
{
item->~int();
}
This code is nearly the same, I just typedef the int to another type and something magic happens:
typedef int myint;
void destruct2 (myint * item)
{
item->~myint();
}
Why does the second code work? Does an int get a destructor just because it has been typedefed?
In case you wonder why one ever would like to do this: This comes from refactoring C++ code. We're removing the standard heap and replacing it with selfmade pools. This requires us to call placement-new and the destructors. I know that calling destructors for primitive types is useless, but we want them in the code nevertheless in case we later replace PODs with real classes.
Finding out that naked int's don't work but typedefed ones do was quite a surprise.
Btw - I have a solution that involves template-functions. We just typedef inside the template and everything is fine.
There has to be only one Destructor in a class. A Destructor has no return type and no parameters. If we do specify a destructor in class then, the compiler creates a default destructor.
A destructor is a member function that is invoked automatically when the object goes out of scope or is explicitly destroyed by a call to delete . A destructor has the same name as the class, preceded by a tilde ( ~ ).
Destructors are usually used to deallocate memory and do other cleanup for a class object and its class members when the object is destroyed. A destructor is called for a class object when that object passes out of scope or is explicitly deleted.
The default destructor calls the destructors of the base class and members of the derived class. The destructors of base classes and members are called in the reverse order of the completion of their constructor: The destructor for a class object is called before destructors for members and bases are called.
It's the reason that makes your code work for generic parameters. Consider a container C:
template<typename T>
struct C {
// ...
~C() {
for(size_t i = 0; i<elements; i++)
buffer[i].~T();
}
};
It would be annoying to introduce special cases for built-in types. So C++ allows you to do the above, even if T happens to equal to int
. The holy Standard says in 12.4 p15
:
The notation for explicit call of a destructor can be used for any scalar type name. Allowing this makes it possible to write code without having to know if a destructor exists for a given type.
The difference between using a plain int and a typedef'ed int is that they are syntactically different things. The rule is, that in a destructor call, the thing after the ~
is a type-name. int
is not such a thing, but a typedef-name is. Look it up in 7.1.5.2
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With