直接上代碼。其實這是對類 和 指標 理解的一個案例。
#include<stdio.h>#include<windows.h>#include<iostream>using std::endl;using std::cout;/*****************事實證明: 類的一般執行個體對象 只在所在函數有效,函數結束,這個類執行個體自動釋放資源。***************/#define DEBUG_FUNCTION_LINE() printf("#當前所在函數 %s() 位於%d行\n",__FUNCTION__,__LINE__)class CServer1{public: int isExit;public: CServer1(){ this->isExit=0; DEBUG_FUNCTION_LINE(); }; ~CServer1(){ this->isExit=1; DEBUG_FUNCTION_LINE(); };};////下面這個 函數 是否有缺陷???CServer1 getPtrFunc (){ CServer1 *s=new CServer1(); s->isExit=15; return *s;//如果不用知怎,局部變數會有錯誤的。Error 返回局部變數地址 是錯誤的。};void func2(){ CServer1 foo; foo=getPtrFunc();//這樣賦值,是否 會存在記憶體流失???當然不會 std::cout<<" foo->isExist=" << foo.isExit <<endl;//=15 是正常的 //結束後,會執行 釋放 操作的!};void func3(){ getPtrFunc();//這樣賦值,是否 會存在記憶體流失???當然不會 //結束後,會執行 釋放 操作的!};int main(){ func2();//兩次 解構函式 cout<<"@@@ Func2 完畢。"<<endl; func3();//一次 解構函式 //這個函數證明了 很是OK ! cout<<"@@@ Func3 完畢。"<<endl; Sleep(20000); return 0;}
結果:
#當前所在函數 CServer1::CServer1() 位於18行#當前所在函數 CServer1::CServer1() 位於18行#當前所在函數 CServer1::~CServer1() 位於22行 foo->isExist=15#當前所在函數 CServer1::~CServer1() 位於22行@@@ Func2 完畢。#當前所在函數 CServer1::CServer1() 位於18行#當前所在函數 CServer1::~CServer1() 位於22行@@@ Func3 完畢。
建構函式 和 解構函式 是一一對應的。所以看到上面 沒有少任何一個函數 ,說明 沒有記憶體流失。
我用了一個 new ,但是沒有delete。沒有記憶體流失。
new的類,利用 函數傳回值(以前我一直認為傳回值 如果是類,必須得用指標呢,其實不用),直接返回類的執行個體對象,而不是指標,這樣,new出來的就不需要delete,也會自然調用 解構函式了。
哈哈,,我好像 是 一個 小學生 突然發現 吸鐵石 S N 互相吸引 ,SS NN互斥 一樣。。。
突然又想 反著來,返回一個指標 類型的,必須 delete 才能避免記憶體流失。但是 發現 使用函數傳回值 我錯了一次。。。
#include<stdio.h>#include<windows.h>#include<iostream>using std::endl;using std::cout;/*****************事實證明: 類的一般執行個體對象 只在所在函數有效,函數結束,這個類執行個體自動釋放資源。***************/#define DEBUG_FUNCTION_LINE() printf("#當前所在函數 %s() 位於%d行\n",__FUNCTION__,__LINE__)class CServer1{public: int isExit;public: CServer1(){ this->isExit=0; DEBUG_FUNCTION_LINE(); }; ~CServer1(){ this->isExit=-1; DEBUG_FUNCTION_LINE(); };};////下面這個 函數 是否有缺陷???CServer1 getPtrFunc (){ CServer1 *s=new CServer1(); s->isExit=15; return *s;//如果不用知怎,局部變數會有錯誤的。Error 返回局部變數地址 是錯誤的。 //這句話 會 調用一個 解構函式};void func1(){ CServer1 foo; cout<<"開始 調用getPtrFunc傳回值"<<endl; foo=getPtrFunc();//這樣賦值,是否 會存在記憶體流失???當然不會 cout<<"結束 調用getPtrFunc傳回值"<<endl; std::cout<<" foo->isExist=" << foo.isExit << " [=15 是正常的]" <<endl;// //結束後,會執行 釋放 操作的!};void func2(){ cout<<"開始 調用getPtrFunc傳回值"<<endl; getPtrFunc();//這樣賦值,是否 會存在記憶體流失???當然不會 cout<<"結束 調用getPtrFunc傳回值"<<endl; //結束後,會執行 釋放 操作的!};CServer1 func31(){ CServer1 * s=new CServer1(); s->isExit=25; *s=getPtrFunc(); std::cout<<"In Func31: foo->isExist=" << s->isExit << " [=15 是正常的]" <<endl;//=15 是正常的 return *s;//本句 導致new的對象 解構函式 被調用了。。。特無語啊。 //return CServer1();};CServer1 * func3(){ //此函數 第一個版本 //CServer1 *s; //s=&func31();//這一句 徹底失敗了。 應該是賦值 而不是 引用地址!! //cout<<"@@@ Func3.1完畢。"<<endl; //Sleep(1); //std::cout<<"In Func3: foo->isExist=" << s->isExit <<endl;//=15 是正常的 //此函數 第二個版本 正常,但是不是我想要的 /***** CServer1 s;//更改為 s 才正常了。 cout<<"開始 調用Func31。"<<endl; s=func31(); cout<<"結束 調用Func31。"<<endl; Sleep(1); std::cout<<"In Func3: foo->isExist=" << s.isExit << " [=15 是正常的]" <<endl;//=15 是正常的 return NULL; *********/ //此函數 第三個版本,修改了傳回值類型;此函數 如果不delete 會記憶體流失 CServer1 *ptr; ptr=new CServer1(); cout<<"開始 調用Func31。"<<endl; *ptr=func31(); cout<<"結束 調用Func31。"<<endl; Sleep(1); std::cout<<"In Func3: foo->isExist=" << (*ptr).isExit << " [=15 是正常的]" <<endl;//=15 是正常的 return ptr; };int main(){ func1();//兩次 解構函式 cout<<"@@@ Func1 完畢。"<<endl<<endl; func2();//一次 解構函式 //這個函數證明了 很是OK ! cout<<"@@@ Func2 完畢。"<<endl<<endl; CServer1 * p=func3(); cout<<"@@@ Func3 完畢。"<<endl<<endl; delete p; cout<<"最後一個函數完成了,delete下 也就沒有記憶體流失了!!"<<endl; Sleep(20000); return 0;}/*#當前所在函數 CServer1::CServer1() 位於18行開始 調用getPtrFunc傳回值#當前所在函數 CServer1::CServer1() 位於18行#當前所在函數 CServer1::~CServer1() 位於22行結束 調用getPtrFunc傳回值 foo->isExist=15 [=15 是正常的]#當前所在函數 CServer1::~CServer1() 位於22行@@@ Func1 完畢。開始 調用getPtrFunc傳回值#當前所在函數 CServer1::CServer1() 位於18行#當前所在函數 CServer1::~CServer1() 位於22行結束 調用getPtrFunc傳回值@@@ Func2 完畢。#當前所在函數 CServer1::CServer1() 位於18行開始 調用Func31。#當前所在函數 CServer1::CServer1() 位於18行#當前所在函數 CServer1::CServer1() 位於18行#當前所在函數 CServer1::~CServer1() 位於22行In Func31: foo->isExist=15 [=15 是正常的]#當前所在函數 CServer1::~CServer1() 位於22行結束 調用Func31。In Func3: foo->isExist=15 [=15 是正常的]@@@ Func3 完畢。#當前所在函數 CServer1::~CServer1() 位於22行最後一個函數完成了,delete下 也就沒有記憶體流失了!!*/
總結:
1.在getPtrFunc 函數中,雖然只有new,由於傳回值 是 類執行個體 類型的,將指標 *p 返回,會在函數完成後自動銷毀(即調用了和new對應delete 對應的 解構函式)。
2.取值 傳回值類型為類執行個體的函數 的時候,不能對函數 使用 & 。正如 func3 的第一個版本,其實已經訪問了釋放過記憶體的地區了。(isExist=-1了)是不安全的。
3.上面說明,函數傳回值 其實在取值的時候 是賦值,而不是 傳遞 地址。將 記憶體 拷貝,複製,有點 memcpy 的感覺。char[] 數組 如果可以這樣賦值 多方便。