2016-04-15 3 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の2つのポインタは、同じヒープ割り当てオブジェクトを指しています。誰がそれを所有していますか?もしあなたがaを削除すると、割り当てられたメモリを削除しなければなりません(間違ってこれをやってはいけませんが)。

このため、std::shared_ptrがあります。それは、このような場合のために設計され、それRight Thing By Magic

std::shared_ptr<int> m_X

int * m_Xを交換しません