2014-09-01 51 views
-2

我的代碼就像下面:爲什麼push_back不會推送源obj的副本?

class CDemo { 
public: 
    CDemo() 
     : str(NULL){ 

      }; 
    ~CDemo() { 
     if (str) 
      delete[] str; 
    }; 
    char* str; 
}; 

void testVector() { 
    CDemo c; 
    c.str = new char[32]; 
    strcpy(c.str, "abcdef"); 
    vector<CDemo>* v = new vector<CDemo>(); 
    v->push_back(c); 
    delete (v); 
    return; 
} 

我知道這是將報告運行時錯誤,因爲我並沒有明確定義一個拷貝構造函數代碼,所以,當testVector返回,成員字段str將被釋放的兩倍,因此報告的error.But什麼使我困惑,就是當我調試到行:delete(v),Visual Studio的快捷方式如下: enter image description here

我認爲功能push_back會導致物品的default copy constructor的致電10,所以在push_back返回後,矢量v的元素應該是與c不同的對象,但是從調試手錶中,我發現它們是相同的address:0x00318100。它是否證明它們實際上是同一個對象? 任何人都可以解釋這一點?

+0

它*推*的對象的副本。你有兩個相同指針的副本。 – chris 2014-09-01 14:52:57

+1

但調試器顯示存儲在'str'中的地址。這正是你自己說你*期待*是一樣的。 – Angew 2014-09-01 14:53:04

+0

'CDemo'的默認拷貝構造函數複製'str'的​​指針值,而不是指向的數據。 – NetVipeC 2014-09-01 14:55:15

回答

0

您正在查看char*地址,該地址被複製爲「」,因爲它是「」,而不是在對象的地址處。

指針的地址可能會不同(您可以通過啓用代碼反彙編模式並查看所涉及的指針和/或通過查看堆棧和內存轉儲來驗證),但它們指向相同的位置。

0

「C」可能被疊加分配:

CDemo c ; 

但你推堆分配指針爲「C」:

c.str=new char[32]; 

所以,你可以添加其他的構造,使得分配一個自己的堆內容的副本:

CDemo(const char* src) :str(new char[strlen(src)+1]) { 
    strcpy(str, src); 
}; 

,比使用這種方式:

vector<CDemo> v; 
v.push_back(new CDemo("abcdef")); 
1

它推送CDemo對象的副本。

但是,兩個副本都包含相同的str指針值。這就是你在調試器中看到的,這就是爲什麼兩個都試圖刪除相同的數組。

要修復的雙重缺失,無論是

  • 使用std::string正確地管理內存爲您服務;或
  • 根據Rule of Three,仔細實現複製構造函數和複製賦值運算符,以正確複製字符串內容,而不是指針。

除非你在教你自己如何管理動態內存,或者有非常特殊的要求,只需使用std::string。一般來說,不要使用new,除非您真的需要 - 特別是沒有理由動態分配向量。

相關問題