C++ 傳值 避免 記憶體流失的一個技巧。[new 了以後,不一定要delete]

來源:互聯網
上載者:User

直接上代碼。其實這是對類 和 指標 理解的一個案例。

#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[] 數組 如果可以這樣賦值 多方便。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.