C + + destructor
The inherited development environment that I use: Visual Studio
How to write a destructor when designing a class.
Destructors if we do not write,C + + will help us to automatically synthesize one, that is to say:C + + will automatically help us write a destructor. Most of the time, automatically generated destructors can work well, but some important deeds require us to write destructors ourselves.
Destructors and constructors are a pair. Constructors are used to create objects, and destructors are used to undo objects. Simply put: When an object is born, use a constructor, and when it dies, use a destructor.
Let's take a look at the following example:
#include <iostream>
#include <string>
using namespace std;
Class noname{public
:
NoName ():p string (new std::string), I (0), D (0) {}
private:
std::string * pstring;
int i;
Double D;
};
int main () {return
0;
}
In a design like the NoName class above, where a member variable is a pointer (std::string *pstring), in the constructor we use new to create the object and use the pstring to manipulate the object. So in this case, we have to design a destructor.
The destructor is written in this way: (You can declare it in the class, the definition is written outside of the class,)
Class noname{public
:
NoName ():p string (new std::string)
, I (0), D (0) {
cout << "constructor is called. "<< Endl;
}
~noname ();
The Noname::~noname () {
cout << destructor was invoked. "<< Endl;
}
The destructor is written like this: ~noname (), which is the only difference from the constructor is that a ~ symbol is added to the front. Destructors are all without arguments, which means that destructors can always write only one.
According to C + + requirements, as long as the new must have the corresponding delete. This new is new in the constructor, which is when you are born. So when we die, when we call the destructor, we have to delete the pointer.
Let's test this by creating a NoName instance object in the main () function:
int main () {
NoName A;
return 0;
}
and add a breakpoint on this line of the main () function, as shown in the figure:
Run the output:
The constructor is called.
the destructor was called.
When a object is defined, the constructor of the NoName class is invoked, and when the main () function is finished, return 0 is executed; After this sentence, the execution field of the main () function ends, so it's time to kill the object A, so it calls the destructor of the NoName class.
So, what happens if we use the New keyword in the main () function to create an instantiated object of the NoName class?
The code in the main () function is as follows:
int main () {
NoName A;
NoName *p = new NoName;
return 0;
}
Run the output:
The constructor is called.
the constructor is called.
the destructor was called.
Here you use the object created by new, and you must use Delete to release it. Keep in mind: New and delete are a pair. The correct code is the following:
int main () {
NoName A;
NoName *p = new NoName;
Delete p;
return 0;
}
Run the output:
The constructor is called.
the constructor is called.
the destructor was called.
the destructor was called.
Constructors and destructors have their respective uses, in constructors we get resources; in destructors, we release resources. Once released, these resources are recycled and can be reused.
For example, we open the file in the constructor and close the open file in the destructor. This is a relatively good practice.
In the constructor, we go to the connection of the database and close the connection of the database in the destructor.
Dynamically allocating memory in the constructor, the dynamically allocated memory is reclaimed in the destructor.
The operation between the constructor and the destructor is to correspond.
If we don't write destructors,C + + will write a destructor for us. C + + Help us write this destructor can only do some very simple work, it will not help us to open the file, connect the database, allocate memory these operations, the corresponding recycling, it will not write to us. So we need to write it ourselves manually. (If you want to do these things, we have to write them ourselves.) )
If we wrote the destructor ourselves, remember three principles:
If you write a destructor, you must write both the assignment constructor and the assignment operator. You can't just write one.
Assignment constructor:
At the time of assignment, it's not about pointer assignment, but about assigning pointers to strings, which is the most critical step.
Because we write a destructor, we have to write the assignment constructor:
Class noname{public
:
NoName ():p string (new std::string)
, I (0), D (0) {
cout << "constructor is called. "<< Endl;
}
NoName (const NoName & other);
~noname ();
Noname::noname (const NoName & other) {
pstring = new std::string;
*pstring = * (other.pstring);
i = other.i;
d = OTHER.D;
}
In addition to writing an assignment constructor, you write an assignment operator.
Class noname{public
:
NoName ():p string (new std::string)
, I (0), D (0) {
cout << "constructor is called. "<< Endl;
}
NoName (const NoName & other);
~noname ();
noname& operator = (const NoName &RHS);
noname& noname::operator= (const NoName &RHS) {
pstring = new std::string;
*pstring = * (other.pstring);
i = other.i;
d = OTHER.D;
return *this;
}
As long as you write a destructor, you must write the assignment constructor and the assignment operator, which is the famous Three laws (rule ofthree)
Summary:
When designing a class, if one of our constructors is not written, then C + + will write a constructor for us. As long as we write a constructor, C + + will not help us write the constructor again.
Constructors can be overloaded, can write many, destructors cannot be overloaded, only one is written. If we don't write destructors, C + + will automatically write a destructor for us. So at work, the destructor that we write is called, and after the call completes, C + + executes the destructor it automatically generates.
If the class we are writing is a class that is not so complex, we may not need to write destructors. If a class has these conditions: Open the file, dynamically allocate memory, and connect to the database. Simply put: So long as the constructor has the keyword new, we need to write the destructor ourselves manually.
So if we write a destructor, we have to pay attention to the three principles: simultaneous writing: destructors, assignment constructors, assignment operators. Complete code:
#include <iostream> #include <string> using namespace std; Class noname{Public:noname ():p string (new std::string), I (0), D (0) {cout << "constructor is called.
"<< Endl;
} NoName (const NoName & other);
~noname ();
noname& operator = (const NoName &RHS);
Private:std::string * pstring;
int i;
Double D;
}; The Noname::~noname () {cout << destructor was invoked.
"<< Endl;}
Noname::noname (const NoName & other) {pstring = new std::string;
*pstring = * (other.pstring);
i = other.i;
D = OTHER.D;
} noname& noname::operator= (const NoName &RHS) {pstring = new std::string;
*pstring = * (rhs.pstring);
i = rhs.i;
D = RHS.D;
return *this;
int main () {NoName A;
NoName *p = new NoName;
Delete p;
return 0; }