2011-10-20 14 views
2

ディープコピーを実行するときにオブジェクトポインタのクローンを作成したいという問題があります。 私はT * t1を持っていますが、* t1.x = * t2.xのように新しいオブジェクトポインタT * t2を作成したいと思います。コピーコンストラクタ内のポインタの引数

私は上記のアプローチを使用している場合の世話をすべきか、物事
T(const T* cpy) 
{ 
    m_var = (*cpy).m_var; 
} 

T* t1 = new T; 
T* t2(t1); 

は、次のように動作しますコピーコンストラクタを書くための良いアイデアですか?これを行うには

おかげ Ruchi

答えて

4

あなたは、通常のコピーコンストラクタを書いて、このようにそれを使用する必要があります:あなたが表示されたコードで

T(const T& cpy) 
: m_var(cpy.m_var) // prefer initialization-list, thanks to @Loki Astari 
{} 

T* t1 = new T; 
T* t2 = new T(*t1); 

T* t2(t1);は、あなたが宣言したコンストラクタを呼び出すことはありません(ちなみにコピーコンストラクタではない)。ポインタt2をポインタt1の値に初期化するだけで、両方が同じオブジェクトを指すようにするためです。

@ Nawazが指摘しているように、このコピーコンストラクタはコンパイラで生成されたものと同等なので、実際に記述する必要はありません。実際、手動で管理されたリソース(通常はそうではない)がない限り、コンパイラーはコピーコンストラクターを生成しても問題ありません。

+1

普通のコピーコンストラクタを書く必要はありません。コンパイラで生成されたもので十分です。 – Nawaz

1

コピーコンストラクタの定義は、参照が必要ですので、次のとおりです。

T(T const& copy)   // This defines a copy constructor. 
    : m_var(copy.m_var)  // Prefer to use the initializer list. 
{} 

ですから、参照を渡す必要があります。
使用状況が続いているポインタをコピーする場合:

T* t2 = new T(*t1); 
0

これは、あなたが考えて何をしていません。

T* t2(t1); 

あなたはポインタだけではなく、オブジェクトを宣言しているため。ポインタは、他のポインタの値に初期化されます。それは次のようになります。

T* t2 = new T (t1); 

新しいオブジェクトを作成します。

コピーに関しては、ポインタ値がコピーされているだけで、ポインタが指すデータではなく、現在は浅いコピーを行っています。浅いコピーを行うと、元のコピーまたはコピーが破棄されたときに問題が発生します.m_varが削除された場合、他のオブジェクトは削除されたメモリへのポインタを持ち、未参照動作TMを参照します。ディープコピーの修正これは:

T(const T* cpy) 
{ 
    m_var = new VarType (cpy->m_var); // VarType being whatever m_var is 
} 

これは今も、上記の削除の問題を防ぐために深くなければなりませんm_varのタイプ、のためのコピーコンストラクタが必要です。

データを深くコピーするという欠点は、メモリを増やし、メモリを割り当ててデータをコピーするのにかなりの時間がかかることです。これは、参照カウントされたオブジェクトを使用して解決できます。これらはいくつかの味があり、スマートポインタが最も一般的です。ここで、同じ基本オブジェクトは、親オブジェクトのすべてのコピーによる参照です。親が削除されると、オブジェクトのスマートポインタのデストラクタは、そのオブジェクトへのすべての参照が削除されると、そのオブジェクトを破棄します。

スマートポインタの欠点は、1つの所有オブジェクトからデータを変更すると、すべての所有オブジェクトに表示されるデータが変更されることです。両方の世界を最大限に活用するには、「修正版のコピー」システムが必要です。これは、基礎となるデータが所有オブジェクトによって変更された場合にのみメモリ使用量を増加させます。

関連する問題