Recently re-review the basic knowledge of C + +, here to share with you, alone pain is not as painful.
Let's put a sample code like this:
classCTest{ Public: CTest (){ This->p =New Char(5); };
~CTest () {if(! This-p) {return; } Delete This-p; This->p =NULL; }
void Mfree () {
Delete this->p;
This->p = NULL;
}Private: Char*P;};
int main () {
CTest *cctest = new CTest ();
CTest tctest = *cctest
Delete cctest;
return 0;
}
Bo Master is in the VS2013 environment run this code, is such a piece of human and animal harmless code, run the time unexpectedly collapsed ..., yes, it's a crash.
This involves the most basic deep copy and shallow copy of the knowledge, tctest as a temporary variable copy the cctest inside the member parameters, but TCTEST.P and Cctest->p point to the same piece of memory.
I think the reason for the crash is this: when the main function executes, the Tctest destructor is executed, and the release Cctest executes the destructor, freeing two times for the same memory to crash.
But vs is to throw such an exception when Cctest frees memory: p points to the memory by the temporary variable tctest occupy so can not be released, this should study the memory scheduling mechanism of C + +, and the source code to determine the deep cause.
So how to avoid this problem? The veteran must have known, refactoring the copy function is OK:
classctest{ Public: CTest () { This->p =New Char(5); }; CTest (CTest&t) { This->p =New Char(5); if(T.P) {memcpy ( This->p, T.P,5);} }; ~CTest () {if(! This-p) {return; } Delete This-p; This->p =NULL; } voidMfree () {Delete This-p; This->p =NULL; }Private: Char*p;};
The old birds must be ripe: ctest a = b; and CTest A (b); the effect is the same.
OK, let's go ahead and add some new gameplay:
classcparant{ Public: Cparant (Const Char*Pchin) { This->choutput =Pchin; } ~cparant () {printf ("exit\n"); }; string&mgetoutputaddr ();Private: stringchoutput;};classCchild: Publiccparant{ Public: Cchild (Const Char*Pchin): Cparant (pchin) { This->p =New Char(5); }; Cchild (Constcchild&ccchild): Cparant (ccchild) { This->p =New Char(5); if(CCCHILD.P) memcpy ( This->p, CCCHILD.P,5); }; voidMfree () {Delete This-p; This->p =NULL; } ~Cchild () {if(! This-p) {return; } Delete This-p; This->p =NULL; }Private: Char*p;};
int main () {
cparant* ccparant = new Ccparant ("father");
Ccparant tccparant = *ccparant
Delete ccparant;
return 0;
}
Would you guess this will be an error? Of course not, you have changed the copy function, how can the error?
The
does not give an error, but not because I refactored the copy function, but because there is no copy of the CHAR *P member variable, and the parent copy is a variable that is not copied to the subclass, even if the assignment is instantiated by a subclass. Although the above example does not cause a program to crash, it is not perfect, it can cause memory leaks. The reason for this is that Ccparant did not call the destructor of the subclass at the time of the destructor. The workaround is as follows:
class cparant{ public : Cparant ( const char * Pchin) { this ->choutput = Pchin; Virtual ~cparant () {printf ( " exit\n " ); }; string & mgetoutputaddr (); private : string choutput;};
The destructor of the parent class is changed to virtual function, so the destructor of the subclass is called first to avoid the memory leak caused by the child class member cannot be freed. As for the effect of adding a virtual function, let's take a look at the following two contrasting images:
When you do not set a virtual destructor:
This is after adding the virtual keyword:
You can see that a virtual function is added to the function pointer table in memory after ccparant, which stores the virtual function implementation of the pointer address. We can also verify it in a different way:
int Main () { ccparant t ("Test"); printf ("%d"sizeof(t));
return 0; }
Compare the size of the change before and after, to see if there is a difference of 4byte, this is said so much, are relatively basic simple things, the next we want to dig deeper, increase strength.
C + + Brain teasers