2013-11-27 159 views
3

我只是在一條簡單的線上浪費了幾個小時而導致數據丟失。我有AnotherClass持有MyClass實例的向量。此AnotherClass實例的MyClass對象以下方式:在C++中創建對象

AnotherClass::AnotherClass(){    
     MyClass myObject(...); 
     myVector.push_back(&myObject); 
} 

myObject的的地址之後推入載體(與MyClass的的其他實例),如寫在代碼。當我開始使用AnotherClass的實例時,我注意到MyClass的值丟失了(完全隨機)。當我將代碼更改爲:

AnotherClass::AnotherClass(){    
     MyClass* myObject = new MyClass(...); 
     myVector.push_back(myObject); 
} 

我沒有數據丟失。

有人可以這麼好解釋爲什麼創建對象的第二種方式不會導致數據丟失? (沒有參考我的書1.000頁)

+0

你有存儲指針而不是對象的特殊原因嗎?如果不是,那麼不要。 –

+0

*「我有AnotherClass持有MyClass實例的向量。」* - 不,你不知道。或者如果你這樣做,它與這段代碼無關,所以我不知道你爲什麼提到它。 –

回答

9

簡單。第一個版本在堆棧上創建一個局部變量,當它超出範圍時會自動銷燬(在函數結束時)

您的向量只包含一個指向過去對象的指針。

第二個版本在堆上創建一個對象,直到最終刪除它爲止。

+0

致謝,謝謝! – Drizzt

2

原因是RAII

在第一個片段中,您在方法/構造函數的作用域中聲明瞭一個對象。 一旦這個範圍結束,當方法結束時,你的對象得到超出範圍,併爲你清除(這意味着它的desctructor被調用)。你的矢量現在仍然持有指向你已經清理過的無效對象,這就是你得到垃圾的原因。

在第二個snippter中,您的對象包含在堆中。除非您撥打delete myObj;,否則他們不會被清除/銷燬。這就是爲什麼即使在方法結束後它們仍然有效的原因。

您可以在多種方式解決這個問題:

  • 聲明你的向量std::vector<MyClass>(注意,不是指針類型)
  • 保持你的第二個片段但一定要刪除向量的所有元素,一旦你做
  • 使用智能指針,如果你通過自己不想清理你的對象(例如std::shared_ptrstd::unique_ptr
+0

感謝您提供豐富的答案和替代解決方案。所以'std :: vector myVector; '和'myVector.push_back(MyClass myObject(...)); '將確保我返回實例時保留信息? – Drizzt

+0

是的,但語法是'myVector.push_back(MyClass(...));'。注意'std :: vector'的訪問器方法返回引用。因此,當您將對象推回時創建副本時,像'myVector [2] = foo;'這樣的代碼將修改vector中的元素爲'myVector [2]'返回一個引用。 – Paranaix

1

第一種方式在堆棧上分配MyClass對象。這個對象在它離開時就會被釋放,也就是說,當構造函數運行時。

第二種方式分配動態內存中的對象。該對象將繼續存在,直到您對其調用delete爲止。

第二種方式是做到這一點,但是你應該向析出器添加一個析構函數來遍歷vector並刪除所有對象。否則你的程序會有內存泄漏。

+0

感謝內存泄漏警告,這可能是我將遇到的下一個問題;-) – Drizzt

+0

不客氣! – greken