Destructor are automatically called at the end of an object's life. The well-known smart pointer is implemented based on the features of destructor, including the memory management mechanism of Qt, this mechanism of destructor is also used for implementation. Bjarne Stroustrup, founder of c ++, is also for this purpose in creating destructor. It can be seen that if the Destructor is used well, we can save a lot of work, you no longer need to manually call the heap memory used by the object. You only need to put the heap memory to be deleted into the destructor, because when the object leaves its lifecycle, the Destructor is automatically called. The C ++ language specification specifies the calling of the Destructor as follows:
Destructors are invoked implicitly (1) for a constructed object with static storage duration (3.7.1) at program termination (3.6.3), (2) for a constructed object with automatic storage duration (3.7.2) when the block in which the object is created exits (6.7), (3) for a constructed temporary object when the lifetime of the temporary object ends (12.2), (4) for a constructed object allocated by a newexpression (5.3.4), through use of a deleteexpression (5.3.5), (5) in several situations due to the handling of exceptions (15.3 ). A program is illformed if an object of class type or array thereof is declared and the destructor for the class is not accessible at the point of the declaration. destructors can also be invoked explicitly.
The general idea is:
Destructor can be implicitly called in the following five ways:
(1) The object constructed in the static storage area (that is, the global object or static object, which is placed in the data area of the Program). When the program ends, the destructor of the object is automatically called.
(2) When an object constructed in the Automatic Storage Area (that is, a local object, which is put in the stack of a program) leaves its region, such as an object declared in a function, when you leave the function scope, the object constructor will automatically call it.
(3) When a temporary constructed object leaves its lifecycle, The destructor of the object will be called. This is the same as (2 ).
(4) The newly constructed object (that is, the object is in the heap area) is deleted through delete, and The Destructor calls
(5) When try and catch handle exceptions, when an object in the try block enters the catch Branch due to exceptions, the constructor will be called in the catch branch.
The above five are the default call methods generated by the compiler. Of course, there is also one that can be called by means of display, that is, calling the Destructor just like calling a function.
With the above introduction, we will go to our topic, delete, but do not call the destructor. This is the same as the (3) of C ++ mentioned above) the following is a simple example:
The example consists of five files: testa. cpp, testa. h, testb. cpp, testb. h, main. cpp
[Html]
Testa. h file
# Ifndef _ TEST_A_H
# Define _ TEST_A_H
Class CTestA {
Public:
CTestA ();
~ CTestA ();
};
# Endif
Testa. h file
# Ifndef _ TEST_A_H
# Define _ TEST_A_H
Class CTestA {
Public:
CTestA ();
~ CTestA ();
};
# Endif
[Html]
Testa. cpp File
# Include "testa. h"
# Include <qdebug. h>
CTestA: CTestA ()
{
}
CTestA ::~ CTestA ()
{
QDebug () <"~ CTestA ()";
}
Testa. cpp File
# Include "testa. h"
# Include <qdebug. h>
CTestA: CTestA ()
{
}
CTestA ::~ CTestA ()
{
QDebug () <"~ CTestA ()";
}
[Html]
Testb. h file
# Ifndef _ TEST_ B _H
# Define _ TEST_ B _H
Class CTestA;
Class CTestB {
Public:
Static CTestB * getInstance ();
CTestA * getTestA ();
Private:
CTestB ();
~ CTestB ();
Private:
CTestA * pTestA;
Static CTestB mSelf;
};
# Endif
Testb. h file
# Ifndef _ TEST_ B _H
# Define _ TEST_ B _H
Class CTestA;
Class CTestB {
Public:
Static CTestB * getInstance ();
CTestA * getTestA ();
Private:
CTestB ();
~ CTestB ();
Private:
CTestA * pTestA;
Static CTestB mSelf;
};
# Endif
[Html]
Testb. cpp File
# Include "testb. h"
# Include "testa. h"
# Include <qdebug. h>
CTestA: CTestA ()
{
}
CTestA ::~ CTestA ()
{
QDebug () <"~ CTestA ()";
}
Testb. cpp File
# Include "testb. h"
# Include "testa. h"
# Include <qdebug. h>
CTestA: CTestA ()
{
}
CTestA ::~ CTestA ()
{
QDebug () <"~ CTestA ()";
}
[Html]
Testapp. h file
# Ifndef _ TEST_APP_H
# Define _ TEST_APP_H
Class CTestA;
Class CTestApp {
Public:
CTestApp (CTestA * pTestA );
~ CTestApp ();
Private:
CTestA * pTestA;
};
# Endif
Testapp. h file
# Ifndef _ TEST_APP_H
# Define _ TEST_APP_H
Class CTestA;
Class CTestApp {
Public:
CTestApp (CTestA * pTestA );
~ CTestApp ();
Private:
CTestA * pTestA;
};
# Endif
[Html]
Testapp. cpp File
# Include "testapp. h"
Testapp. cpp File
# Include "testapp. h" [html] view plaincopyprint? <SPAN style = "FONT-FAMILY: arial"> # include <qdebug. h> </SPAN>
# Include <qdebug. h> [html] view plaincopyprint? <SPAN style = "FONT-FAMILY: arial"> // # include "testa. h" </SPAN>
// # Include "testa. h" [html] view plaincopyprint? CTestApp: CTestApp (CTestA * pTestA)
{
This-> pTestA = pTestA;
}
CTestApp ::~ CTestApp ()
{
Delete pTestA;
QDebug () <"~ CTestApp ()";
}
CTestApp: CTestApp (CTestA * pTestA)
{
This-> pTestA = pTestA;
}
CTestApp ::~ CTestApp ()
{
Delete pTestA;
QDebug () <"~ CTestApp ()";
}
[Html]
Main. cpp File
# Include "testb. h"
# Include "testcpp. h"
Int main (int argc, char * argv [])
{
QApplication app (argc, argv );
CTestB * pTestB = CTestB: getInstance ();
CTestApp * pTestApp = new CTestApp (pTestB-> getTestA ());
Delete pTestApp;
Return app.exe c ();
}
Main. cpp File
# Include "testb. h"
# Include "testcpp. h"
Int main (int argc, char * argv [])
{
QApplication app (argc, argv );
CTestB * pTestB = CTestB: getInstance ();
CTestApp * pTestApp = new CTestApp (pTestB-> getTestA ());
Delete pTestApp;
Return app.exe c ();
} The following is the output result,
~ CTestApp ()
Delete pTestA. After that, the destructor of pTestA is not called. // # include "testa. h "uncomment. After delete, The pTestA destructor is called. This is the output result after the annotation is removed:
~ CTestA ()
~ CTestApp ()
Note that the above compilation environment is a ming32-make, do not know other compilation environment will not have such a problem, this left for everyone to verify.
The following is the disassembly code, which adds the delete pTestA disassembly code of testa. h In testapp. cpp:
Delete pTestA; 0x0040255c <+ 8>: mov 0x8 (% ebp), % eax0x0040255f <+ 11>: mov (% eax), % ebx0x00402561 <+ 13>: test % ebx, % ebx0x00402563 <+ 15>: je 0x402575 <~ CTestApp + 33> 0x00402565 <+ 17>: mov % ebx, (% esp) 0x00402568 <+ 20>: call 0x403082 <~ CTestA> 0x0040256d <+ 25>: mov % ebx, (% esp) 0x00402570 <+ 28>: call 0x40aa68 <_ ZdlPv>
This is the delete pTestA disassembly code without testa. h In testapp. cpp:
Delete pTestA; 0x00402550 <+ 8>: mov 0x8 (% ebp), % eax0x00402553 <+ 11>: mov (% eax), % eax0x00402555 <+ 13>: mov % eax, (% esp) 0x00402558 <+ 16>: call 0x40aa48 <_ ZdlPv> you can see that testa is added. in the disassembly of h, the Destructor ~ CTestA, call 0x403082 <~ CTestA>