I have class Item
which defines its own operator new and operator delete as follows:
class Item
{
public:
Item(const std::string &s):msg(s)
{
std::cout<<"Ctor: "<<msg<<std::endl;
}
static void* operator new(size_t size, int ID, const std::string &extra)
{
std::cout<<"My Operator New. ID/extra: "<<ID<<"/"<<extra<<std::endl;
return ::operator new(size);
}
static void operator delete(void* p)
{
std::cout<<"My Operator Delete"<<std::endl;
return;
}
~Item()
{
std::cout<<"Destructor: "<<msg<<std::endl;
}
void Print()
{
std::cout<<"Item::msg: "<<msg<<std::endl;
}
private:
std::string msg;
};
I create an object of this type by using a placement new and then delete as follows:
int main()
{
Item *pI=new(1,"haha")Item("AC Milan");
std::cout<<"before delete"<<std::endl;
delete pI;
std::cout<<"after delete"<<std::endl;
return 0;
}
The output is:
My Operator New. ID/extra: 1/haha
Ctor: AC Milan
before delete
Destructor: AC Milan
My Operator Delete
after delete
As you can see, delete pI
calls my own delete function in which nothing is done except outputting a log. However, from the output, the destructor of Item
is called in delete pI
which isn't invoked in my own delete function.
So in this case, destructor would be called implicitly in a overloaded delete function?
When delete is used to deallocate memory for a C++ class object, the object's destructor is called before the object's memory is deallocated (if the object has a destructor). If the operand to the delete operator is a modifiable l-value, its value is undefined after the object is deleted.
New and Delete operators can be overloaded globally or they can be overloaded for specific classes. If these operators are overloaded using member function for a class, it means that these operators are overloaded only for that specific class.
So delete is for managing the dynamic memory, but the destructor is a method of the class itself, which is always called when the object is getting freed from the memory (stack or heap).
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.
It's called the deleting destructor and its existence is described by the Itanium C++ ABI: deleting destructor of a class T - A function that, in addition to the actions required of a complete object destructor, calls the appropriate deallocation function (i.e,. operator delete) for T. The ABI goes on to provide more details:
It shouldn't call the deleting destructor, because it does not actually delete an object from the heap. It is also interesting to examine how the destructor (s) of Animal look, since unlike Sheep, Animal does not define a custom operator delete: As expected, the destructor of Animal calls the global ::operator delete.
In C#, destructor (finalizer) is used to destroy objects of class when the scope of an object ends. It has the same name as the class and starts with a tilde ~.
The compiler mimics "virtuality" of operator delete by invoking it from the destructor. Since the destructor is virtual, what ends up called eventually is the destructor for the dynamic type of the object. In our example this would be the destructor of Sheep, which can call the right operator delete since it's in the same static scope.
So in this case, destructor would be called implicitly in a overloaded delete function?
Yes. For a delete expression, (1)the destructor will be invoked firstly, then (2)the apporiate operator delete
will be invoked; name lookup and overload resolution will be performed at this stage.
If expression is not a null pointer, the delete expression invokes the destructor (if any) for the object that's being destroyed, or for every element of the array being destroyed (proceeding from the last element to the first element of the array).
After that, unless the matching new-expression was combined with another new-expression (since C++14) the delete expression invokes the deallocation function, either
operator delete
(for the first version of the expression) oroperator delete[]
(for the second version of the expression).
The destructor is not called by an overloaded operator delete()
function.
However, a delete
expression (in your case, delete pI
) has the effect of first invoking the destructor for the object, and then calling the appropriate overload of operator delete()
.
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