1

タイプ B のポインターのリストを含むクラス A のコピー コンストラクターを作成しようとしています。

class A
{
 private:
   list<B*> myList;
   list<B*>::iterator iter;

public:
  A()
  {
   }

 // Copy constructor
 A(const A &src)
  {
    myList.assign(src.myList.begin(), src.myList.end());
  }

A& operator= (const A &src);

 };

A& A::operator= (const A &src)
{
// do the copy
myList.assign(src.myList.begin(), src.myList.end());

// return the existing object
return *this;
}

さて、私の問題は、これを行う場合:

A=a1;

//call function that will change a1

A  a2(a1);

//call function that will change a1

次に、a1 を変更するこの最後の関数を呼び出した後、a2 も変更されていることに気付きました。コピーコンストラクターがこれを防ぐはずだと思っていましたが、コードで何が間違っているのかわかりません。

4

2 に答える 2

4

あなたstd::listはポインタのリストです。
コピー コンストラクターは、これらのポインターの浅いコピーを実行します。a1コピー コンストラクターが両方を呼び出した後、a2要素が同じオブジェクトを指すリストです。
これを回避したい場合は、次のいずれかを行います。

  1. std::listメンバーにポインターではなくオブジェクトを単純に格納するか、
  2. コピー コンストラクターは、ディープ コピーを実行する必要があります。

あるポインターを別のポインターに割り当てると、浅いコピーが実行されます。簡単に言えば、代入後、両方のポインターが同じオブジェクトを指します。あなたのコードは以下とほぼ同等です:

#include<iostream>

using namespace std;

int main()
{
    int i = 10;
    int *ptr = &i;
    int *ptr2 = ptr;

    std::cout<<"\ni = "<<i;
    std::cout<<"\n*ptr = "<<*ptr;
    std::cout<<"\n*ptr2 = "<<*ptr2;

    *ptr2 = 20;

    std::cout<<"\ni = "<<i;
    std::cout<<"\n*ptr = "<<*ptr;
    std::cout<<"\n*ptr2 = "<<*ptr2;

    return 0;
}

出力:

i = 10
*ptr = 10
*ptr2 = 10
i = 20
*ptr = 20
*ptr2 = 20
于 2013-03-08T03:23:33.240 に答える
2

現在のコピー コンストラクターは、実際には、自分で実装しなかった場合に自動的に生成されるコピー コンストラクターと同等です。つまり、ポインターであるリストのすべての要素をコピーします。リスト オブジェクトをコピーして元のオブジェクトに変更を加えた場合 (要素の追加や削除など)、それらの変更はコピーには反映されません。ただし、リストにはオブジェクトへのポインターのみが格納されるため、リストに格納されているオブジェクトへの変更はコピーに反映されます。その動作が望ましくない場合は、実際の B オブジェクトをリストに保存する必要があります。

list<B> mylist;

もちろん、それは B がコピー可能でなければならないことを意味します。

于 2013-03-08T03:28:24.307 に答える