Statement:
Before reading this section, I hope you have read an example program for resource leakage shown in the previous section. Only when we find the problem and look at the solution provided can we find its beauty. I have a deep understanding of this. If you come up with this example, you may not be able to see its perfection. However, if you want to explore the reasons for doing so, you can trace the source, by exploring its step-by-step development process, we can discover its greatness. You can't help but wonder, smart pointer, real intelligence.
Sample Code:
The use of smart pointers eliminates Image Heap Memory leakage in the previous section. It is easy to use and has a very good idea.
# Include <iostream> # include <time. h ># include <memory> using namespace std;/* Author: lpstudy Date: Content: more effective C ++ exception Chapter 10th, prevent heap memory resource leakage in the constructor. Use a smart pointer to complete */# define TRACE_FUCTION_AND_LINE (fmt ,...) printf ("[% 30 s: % 4d]" fmt "\ n" ,__ FUNCTION __, _ LINE __, ##__ VA_ARGS _) class Image {public: image (const string & strImgName): m_strImgName (strImgName) {TRACE_FUCTION_AND_LINE ();}~ Image () {TRACE_FUCTION_AND_LINE ();} private: const string & m_strImgName;};/* The AudioClip class is constructed only after the image class is constructed, the following AudioClip throws an exception and can be used to observe the image destructor. In fact, the image memory leakage is caused by the exception that is not called. */Class AudioClip {public: AudioClip (const string & strAudioName): m_strAudioName (strAudioName) {TRACE_FUCTION_AND_LINE (); throw 1; // The BookEntry throws an exception, the Image structure is not called }~ AudioClip () {TRACE_FUCTION_AND_LINE ();} private: const string & m_strAudioName ;};/* The BookEntry constructor initializes the Image and AudioClip, in this way, if the constructor of Image and AudioClip encounters an exception, the BookEntry constructor will immediately return the result, so that the constructed object is not a complete object. */Class BookEntry {public: BookEntry (const string & name, const string & address = "", const string & imageFileName = "", const string & audioclipName = ""): m_strName (name), m_strAddress (address), m_pImage (imageFileName. empty ())? 0: new Image (imageFileName), m_pAudioClip (audioclipName. empty ())? 0: new AudioClip (audioclipName) {TRACE_FUCTION_AND_LINE ();}~ BookEntry () {// there is no need to call this delete, auto_ptr will do this for us perfectly !!! // Delete m_pImage; // delete m_pAudioClip; TRACE_FUCTION_AND_LINE ();} void Log () {TRACE_FUCTION_AND_LINE ("My Log ------"); throw 1;} private: string m_strName; string m_strAddress; auto_ptr <Image> m_pImage; auto_ptr <AudioClip> m_pAudioClip ;};/* When the constructor is abnormal, due to auto_ptr protection, although audioclip encounters an abnormal Image, the memory is still released normally. */Void TestStackMemory () {try {TRACE_FUCTION_AND_LINE (""); BookEntry bookEntry ("lpstudy", "beijing", "imageFileName", "audioClipName ");} catch (int e) {TRACE_FUCTION_AND_LINE ("exception int = % d", e) ;}/ * When testing heap memory, when the constructor is abnormal, we can see that pBookEntry has not been fully constructed at this time, and the returned pointer is actually NULL. However, due to the auto_ptr memory protection, the Image memory is correctly released. */Void TestHeapMemory () {BookEntry * pBookEntry = 0; try {TRACE_FUCTION_AND_LINE (""); pBookEntry = new BookEntry ("lpstudy", "beijing", "imageFileName ", "audioClipName");} catch (int e) {TRACE_FUCTION_AND_LINE ("exception int = % d", e); TRACE_FUCTION_AND_LINE ("pBookEntry = % 08 p", pBookEntry ); delete pBookEntry; // actually delete null, with no meaning} int main () {TRACE_FUCTION_AND_LINE ("Trace BookEntry ....... "); TestStackMemory (); TestHeapMemory ();/* difference between const auto_ptr and auto_ptr const auto_ptr cannot change the maintained pointer itself, but can change the value of the maintained pointer. Similar to: char * const p = "p100"; so for the above Image object, even if its pointer needs to be of the const type, use const auto_ptr <Image> to */string * p1 = new string ("p100"); string * p2 = new string ("p200 "); const auto_ptr <string> pAutoptrString (p1); const auto_ptr <string> pAutoptrString2 (p2); // pAutoptrString. reset (p2); // reset is a non-const member function and cannot be called by a const object. The non-const object can call both the const member function and the non-const member function pAutoptrString. get ()-> assign ("another p100"); TRACE_FUCTION_AND_LINE ("p1 = % s, p2 = % s", pAutoptrString. get ()-> c_str (), pAutoptrString2.get ()-> c_str (); return 0 ;}/ * use the smart pointer auto_ptr, both the const and non-const pointers can have the same processing result. The code is simple and clear and has great practical value. */