Detail the destructor in C++

  • 2020-10-07 18:48:26
  • OfStack

Introduction to the

Destructors (Destructors), which are member functions of an object, have no return values or arguments, and have only one destructor per class, are called when the object is destroyed, which is usually the case.

Function execution ends End of program execution A local variable that a block contains delete operation

When do You write your own destructor?

The compiler automatically creates default destructors, which is usually fine, but when we dynamically allocate memory space in a class, we need to recycle that space to prevent memory leaks. Like this


class String 
{ 
private: 
	char *s; 
	int size; 
public: 
	String(char *); // constructor 
	~String();	 // destructor 
}; 
 
String::String(char *c) 
{ 
	size = strlen(c); 
	s = new char[size+1]; 
	strcpy(s,c); 
} 
 
String::~String() 
{ 
	delete []s; 
} 

Private destructor

You can set the access to the destructor to private, which is fine, but the one problem is that the usual method doesn't call the destructor.

As shown below, the destructor is called at the end of the program, but the destructor is private and cannot be called, so a compilation error occurs.


#include <iostream> 
using namespace std; 
class Test { 
private: 
	~Test() {} 
}; 
int main() 
{ 
	Test t; 
} 

This is fine because no objects are created and no destructions are needed


int main() 
{ 
 Test* t;           
} 

This is also fine, because dynamically allocated memory requires programmer means to free it, so the program ends without freeing memory or calling destructors. If the dynamically allocated memory is not released manually, the program will not be released after the end of the program, but the modern operating system can help us to release, because the dynamically allocated memory is related to the process, the operating system should be able to capture the leaked memory to release. (I looked it up)


int main() 
{ 
 Test* t = new Test; 
} 

If you use delete to delete objects, a compilation error occurs


int main() 
{ 
 Test* t = new Test;
 delete t;// Compilation error, unable to call private destructor  
}

You can use the Friend function for object destruction because Friend has access to private members, so you can access destructors.


#include <iostream> 

class Test { 
private: 
	~Test() {} 
	friend void destructTest(Test*); 
}; 

void destructTest(Test* ptr) 
{ 
	delete ptr; 
} 

int main() 
{ 
	Test* ptr = new Test; 
	destructTest(ptr); 

	return 0; 
} 

Or write a destroy method to the class, calling it when it needs to be destroyed.


class Test { 
public:
 destroy(){delete this};
private: 
	~Test() {} 
};

So when do you need to use private destructors? When we only want to allocate object space dynamically (on the heap), using private destructors prevents allocation on the stack, because errors occur at compile time.

Virtual destructor

Virtual destructors are used when classes use polymorphic properties. Look at the following example.


#include <iostream>
using namespace std;
class Base
{
public:
 Base(){
  cout << "Base Constructor Called\n";
 }
 ~Base(){
  cout << "Base Destructor called\n";
 }
};
class Derived1: public Base
{
public:
 Derived1(){
  cout << "Derived constructor called\n";
 }
 ~Derived1(){
  cout << "Derived destructor called\n";
 }
};
int main()
{
 Base *b = new Derived1();
 delete b;
}

The destructor in the example is not a virtual function, when we want to use the base class pointer to delete derived class objects, there is a problem, "undefined behavior", c++ standard, only implemented by the compiler, usually this will not report an error, will call the base class destructor. But that shouldn't be what we want, and that could lead to a memory leak. So you want to make the destructor virtual. (msvc doesn't seem to add virtual to destructor, default is virtual, gcc doesn't add default.)

In addition, the virtual destructor can be pure virtual destructor, but to provide the body of the function, otherwise there is no destructor, because the virtual destructor and the 1-like virtual function overide is not the same, virtual destructor to be executed one by one, do not provide the body of the function, will compile error.

The order in which destructors are executed

Derived classes, member objects, base classes like that


class B
{public: virtual ~B(){cout<<" The base class B To perform the "<<endl; }
};

class D
{public:virtual ~D(){cout<<" Members of the D To perform the "<<endl; }
} ;

class E
{public:virtual ~E(){cout<<" Members of the E To perform the "<<endl; }
} ;

class A
{public:virtual ~A(){cout<<" The base class A To perform the "<<endl;}; 
};

class C:public A,B
{
 public:virtual ~C(){cout<<" The derived class executes "<<endl;};
 private:
  E e;
  D d;
};

int main() 
{ 
 C *c;
 c=new C();
 delete c;
} 

The results for

[

The derived class executes
Member D was implemented
Member E performed
The base class B is executed
The base class A executes

]

reference

[1] when to use virtual functions https: / / stackoverflow com/questions / 461203 / when - to - use virtual - destructors
[2] the destructor https: / / www geeksforgeeks. org/destructors c /
[3] virtual destructors https: / / www geeksforgeeks. org/virtual destructor /
[4] pure destructor https: / / www geeksforgeeks. org/pure - virtual - destructor - c /

That is the detailed explanation of the destructors in C++, more information about C++ destructors please follow the other articles on this site!


Related articles: