2016-04-15 55 views
0

任何人都可以解釋爲什麼在此代碼定義MyClass (const MyClass & src) { m_X = src . m_X; }?如果沒有這行代碼,它也可以很好地工作,並給出相同的輸出,在這種情況下爲32。有和沒有有什麼區別?我讀過複製構造函數是自動創建的,但是當你在類中定義了指針時,你應該定義它,但是在這種情況下我不明白爲什麼。下面複製構造函數混淆

代碼:

#include <iostream> 
using namespace std; 

class MyClass 
{ 
public: 
    MyClass (int x) : m_X (new int (x)) {} 
    MyClass (const MyClass &src) 
    { 
     m_X = src.m_X; 
    } 

    void print (void) const 
    { 
     cout << *m_X; 
    } 

private: 
    int * m_X; 
}; 


int main (void) 
{ 
    MyClass a (32), c = a; 
    c.print(); 

    return 0; 
} 

回答

1

你得到的結果相同的是你正在做一個淺拷貝就像編譯器會做的原因。僅僅複製一個指針是不夠的。您需要創建一個新指針,然後將其值設置爲您正在複製的副本。一個合適的構造函數看起來像

MyClass (const MyClass & src) : m_X(new int(*src.m_X) {} 

現在副本具有自己的獨立指針,它具有相同的值。

另請注意,您需要一個析構函數來刪除內存和一個適當的複製賦值運算符,因爲默認的複製賦值運算符將執行與默認的複製構造函數相同的操作。

2

默認拷貝構造函數以及您的拷貝構造函數都會執行成員明智拷貝(或淺拷貝)。在這種情況下,您有一個指針,其值是數據所在的地址。這個地址是被複制的。

正如其他帖子所指出的,您將需要更好地管理指針。

2

編譯器生成的問題之一(和你的)是它複製指針。您現在有兩個指針c.m_xa.m_x都指向相同的堆分配對象。誰擁有它?如果你刪除一個,會發生什麼情況,它應該刪除它分配的內存(你錯誤地不這樣做),但是c仍然在對它進行注入。

由於這個原因,有std::shared_ptr。它是專爲這種情況下,它的Right Thing By Magic

通過std::shared_ptr<int> m_X

更換 int * m_X