欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
深拷貝、淺拷貝 構造函數問(wèn)題

深拷貝、淺拷貝構造函數問(wèn)題


Trend科技的一道面試題:

請看下面的程序,說(shuō)說(shuō)會(huì )出現什么問(wèn)題?

#include <iostream>

#include <cstdlib>

#include <vector> 

using   namespace   std; 

 

class   CDemo  

{ 

public: 

    CDemo():str(NULL){}; 

    ~CDemo()  

    {  

        if(str)   delete[]   str;  

    }; 

    char*   str; 

}; 

 

int  main(int   argc,   char**   argv)  

{ 

    CDemo   d1; 

    d1.str=new   char[32]; 

    strcpy(d1.str, "trend   micro"); 

 

    vector<CDemo>   *a1=new   vector<CDemo>(); 

   

    a1->push_back(d1);

    delete   a1;

  

    return EXIT_SUCCESS;

}



這個(gè)程序在退出時(shí),會(huì )出問(wèn)題,什么問(wèn)題?重復delete同一片內存,程序崩潰。
我們把析構函數改為如下,可以更清楚的看到這一點(diǎn):
 
~CDemo() 

{ 

    if(str)

    {

        static int i=0;

        cout<<"&CDemo"<<i++<<"="<<(int*)this<<",    str="<<(int *)str<<endl;

        delete[]   str;    

    }

};

 
  
運行時(shí)我們發(fā)現打印如下信息:
&CDemo0=000309D8,       str=000307A8
&CDemo1=0013FF70,       str=000307A8
也就是說(shuō),發(fā)生了CDemo類(lèi)的兩次析構,兩次析構str所指向的同一內存地址空間(兩次str值相同=000307A8)。
為什么?

《程序員面試寶典》第二版,P99,有句解釋“vector對象指針能夠自動(dòng)析構,所以不需要調用deletea1,否則會(huì )造成兩次析構對象

我切以為這句話(huà)說(shuō)的有點(diǎn)不妥。任何對象如果是通過(guò)new操作符申請了空間,必須顯示的調用delete來(lái)銷(xiāo)毀這個(gè)對象。所以“delete  a1;  ”這條語(yǔ)句是沒(méi)有錯誤的。
這句話(huà)vector<CDemo>   *a1=new   vector<CDemo>();定一個(gè)指針,指向 vector<CDemo>,病用new操作符進(jìn)行了初始化, 我們必須在適當的時(shí)候釋放a1所占的內存空間,所以“delete  a1;  ”這句話(huà)是沒(méi)有錯誤的。另外,我們必須明白一點(diǎn),釋放vector對象,vector所包含的元素也同時(shí)被釋放。

那到底那里錯誤?

這句a1的聲明和初始化語(yǔ)句

vector<CDemo>   *a1=new   vector<CDemo>();  ”

說(shuō)明a1所含元素是“CDemo”類(lèi)型的,在執行“a1->push_back(d1); ”這條語(yǔ)句時(shí),會(huì )調用CDemo的拷貝構造函數,雖然CDemo類(lèi)中沒(méi)有定義拷貝構造函數,但是編譯器會(huì )為CDemo類(lèi)構建一個(gè)默認的拷貝構造函數(淺拷貝),這就好像任何對象如果沒(méi)有定義構造函數,編譯器會(huì )構建一個(gè)默認的構造函數一樣。

正是這里出了問(wèn)題。a1中的所有CDemo元素的str成員變量沒(méi)有初始化,只有一個(gè)四字節(32位機)指針空間。
“a1->push_back(d1);”
這句話(huà)執行完后,a1里的CDemo元素與d1是不同的對象,但是a1里的CDemo元素的strd1.str指向的是同一塊內存,這從后來(lái)的打印信息就可以看出來(lái)。

我們知道,局部變量,如“CDemo  d1;  ” main函數退出時(shí),自動(dòng)釋放所占內存空間,
那么會(huì )自動(dòng)調用CDemo的析構函數“~CDeme”,問(wèn)題就出在這里。

前面的“delete   a1;”已經(jīng)把 d1.str 釋放了(因為a1里的CDemo元素的strd1.str指向的是同一塊內存),main函數退出時(shí),又要釋放已經(jīng)釋放掉的 d1.str 內存空間,所以程序最后崩潰。




解釋清楚了。
這里最核心的問(wèn)題歸根結底就是淺拷貝和深拷貝的問(wèn)題。如果CDemo類(lèi)添加一個(gè)這樣的拷貝構造函數就可以解決問(wèn)題:
   
CDemo(const  CDemo   &cd)

  {

        this->str   =   new   char[strlen(cd.str)+1];

        strcpy(str,cd.str);

   };

//這就是深拷貝

。

//或者這樣用:

vector<CDemo*>   *a1=new   vector<CDemo*>();

a1->push_back(&d1);

     
那么在   “delete   a1;” a1釋放,同時(shí)a1里面包含的元素(”CDemo*“類(lèi)型,仍然是一個(gè)指針,4字節空間)。

下面的函數是驗證::: 


#include <iostream>

#include <cstdlib>

#include <vector> 

using   namespace   std; 

 

class   CDemo  

{ 

public: 

    CDemo():str(NULL)

       {

              cout <<"構造函數"<< endl;

       };

      

          CDemo(const   CDemo   &cd)//這就是深拷貝

          {

                 cout <<"深拷貝構造函數begin!!!"<<endl;

                 this->str   =   new   char[strlen(cd.str)+1];

                 strcpy(str,cd.str);

                

                  cout <<"深拷貝構造函數 end endend end !!!@@@"<<endl;

          };

         

      

    ~CDemo()        

       {

             

              if(str)

                    

              {

                    

                     static int i=0;

                    

                     cout<<"析構函數:"<<"&CDemo"<<i++<<"="<<(int*)this<<",    str="<<(int *)str<<endl;

                    

                     delete[]   str;   

                    

              }

             

       };

    char*   str; 

}; 

 

int  main(int   argc,   char**   argv)  

{ 

       int k =1;

      

       cout<<"構造CDemo   d1; begin!!!"<<endl;

    CDemo   d1;

       cout<<"d1構造函數對應的值:"<<"&CDemod1="<<(int*)&d1<<",  "<<endl;

       cout<<"構造CDemo   d1; end end end end end end end end!!!!!!@@@"<<endl<<endl<<endl;

   

       d1.str=new   char[32]; 

    strcpy(d1.str, "trend   micro"); 

 

 

       cout<<"構造vector<CDemo*>   *a1; begin!!!"<<endl;

       vector<CDemo*>   *a1=new   vector<CDemo*>();

       cout<<"構造vector<CDemo*>   *a1; end end end end end end!!!!!!@@@!!!"<<endl<<endl<<endl;

 

       cout<<"a1->push_back(d1);begin"<<endl;

       a1->push_back(&d1);

       cout<<"a1->push_back(d1);end end end end!!!!@@@@@@!!!"<<endl<<endl<<endl;

 

       cout<<"析構   a1; begin!!!"<<endl;

       cout<<"a1的元素d1對應的值:"<<"&CDemod1="<<(int*)a1->at(0)<<",  "<<endl;

    delete   a1;

       cout<<"析構   a1; end end end end end end end endend!!!!@@@@@@"<<endl<<endl<<endl;

 

 

 

 

 

//     if (k)

//     {

//            cout<<"構造CDemo   d2; begin!!!"<<endl;

//            CDemo   d2;

//            cout<<"d2構造函數對應的值:"<<"&CDemod2="<<(int*)&d2<<", "<<endl;

//            cout<<"構造CDemo   d2; end end end end end endend!!!!@@@@@@!!!"<<endl<<endl<<endl;;

//           

//            d2.str=new   char[32]; 

//            strcpy(d2.str,"trend   micro22222"); 

//            vector<CDemo>   *a2=new  vector<CDemo>();

//           

//            cout<<"a2->push_back(d2);begin"<<endl;

//            a2->push_back(d2);

//            cout<<"a2->push_back(d2);end end end end!!!!@@@@@@!!!"<<endl<<endl<<endl;

//           

//            cout<<"析構   a2; begin!!!"<<endl;

//            cout<<"a2的元素d2對應的值:"<<"&CDemod2="<<(int*) &(a1->at(0)) <<",  "<<endl;

//            deletea2;

//            cout<<"析構   a2; end end end end@@@@@@"<<endl<<endl<<endl;

//           

//           

//     }

 

       cout<<endl<<endl<<endl<< endl;

      

       cout<<"下一步就是return0"<<endl;

    return EXIT_SUCCESS;

}

 

構造CDemo   d1; begin!!!

構造函數

d1構造函數對應的值:&CDemo d1=0012FF6C,

構造CDemo   d1; end end end end end end end end!!!!!!@@@

 

 

構造vector<CDemo*>   *a1; begin!!!

構造vector<CDemo*>   *a1; end end end end end end!!!!!!@@@!!!

 

 

a1->push_back(d1); begin

a1->push_back(d1); end end endend!!!!@@@@@@!!!

 

 

析構   a1; begin!!!

a1的元素d1對應的值:&CDemod1=0012FF6C,

析構   a1; end end end end end end end endend!!!!@@@@@@

 

 

 

 

 

 

下一步就是return 0

析構函數:&CDemo0=0012FF6C,   str=003807E0

Press any key to continue

 

 

如果放開(kāi) 被隱藏的if()

則結果如下:

構造CDemo   d1; begin!!!

構造函數

d1構造函數對應的值:&CDemo d1=0012FF6C,

構造CDemo   d1; end end end end end end end end!!!!!!@@@

 

 

構造vector<CDemo*>   *a1; begin!!!

構造vector<CDemo*>   *a1; end end end end end end!!!!!!@@@!!!

 

 

a1->push_back(d1); begin

a1->push_back(d1); end end end end!!!!@@@@@@!!!

 

 

析構   a1; begin!!!

a1的元素d1對應的值:&CDemod1=0012FF6C,

析構   a1; end end end end end end end endend!!!!@@@@@@

 

 

構造CDemo   d2; begin!!!

構造函數

d2 構造函數對應的值:&CDemo d2=0012FF64,

構造CDemo   d2; end end end end end end end!!!!@@@@@@!!!

 

 

a2->push_back(d2); begin

深拷貝構造函數begin!!!

深拷貝構造函數 endend end end !!!@@@

a2->push_back(d2); end end endend!!!!@@@@@@!!!

 

 

析構   a2; begin!!!

a2的元素d2對應的值:&CDemod2=20202064,

析構函數:&CDemo0=00380A78,   str=00380AB0

析構   a2; end end end end @@@@@@

 

 

析構函數:&CDemo1=0012FF64,    str=003809D8

 

 

 

 

下一步就是return 0

析構函數:&CDemo2=0012FF6C,   str=003807E0

Press any key to continue

本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
C++ 三大函數該寫(xiě)就要寫(xiě)
C++11 lambda表達式
構造函數 析構函數 拷貝構造函數 this指針的使用
深拷貝與淺拷貝到底是什么
vector用完后需要釋放嘛?
王升的共享空間: STL
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久