0

operator+ をオーバーロードしているときに奇妙なことが起こりました

単方向リストがあり、operator+ と operator= をオーバーロードしました

これが両方の私の実装です(編集:insertFrontとコピーコンストラクターを使用):

 AnyList::AnyList(const AnyList& list)
{
count = list.getCount();
first = list.getFirst();
AnyList a;
a.setFirst(first);
a.setCount(count);

Node *current = first;
for (int i = 0; i < count; ++i)
{
    a.insertFront(current->getData());
    current = current ->getLink();
}
}

-

      void AnyList::insertFront(int value)
{
Node *newNode = new Node;
newNode -> setData(value);
newNode -> setLink(first);
first = newNode;
++count;
}

AnyList AnyList::operator+ (const AnyList& list) const
{

Node *current = first;
Node *listCurrent = list.getFirst();

int sumHolder = 0;
AnyList temp;
while(current != NULL)
{
    sumHolder = current ->getData() + listCurrent ->getData();
    temp.insertFront(sumHolder);
    current = current ->getLink();
    listCurrent = listCurrent ->getLink();
}

return temp;
}


AnyList& AnyList::operator=(const AnyList& rightSide)
{

if(&rightSide != this)
{
    Node *travel = rightSide.getFirst();

    first = rightSide.getFirst();

    Node *original = first;

    while (travel != NULL)
    {
        original ->setData(travel ->getData());
        original ->setLink(travel ->getLink());
        travel = travel->getLink();
        original = original ->getLink();
    }
}

return *this;
}

主なものは次のとおりです。

AnyList mylist;
AnyList mylist2;

for (int i = 0; i < 10; ++i)
{
    mylist.insertFront(i);
}
for (int i = 10; i < 20; ++i)
{
    mylist2.insertFront(i);
}

mylist.print();
cout << endl << endl;
mylist2.print();
cout << endl;
AnyList sumList = mylist + mylist2;
sumList.print();
cout << endl;

私の出力は次のとおりです(これは私が望んでいた出力です):

    9 8 7 6 5 4 3 2 1 0 

19 18 17 16 15 14 13 12 11 10

10 12 14 16 18 20 22 24 26 28 

だから、私の質問は、私が代わりに書くときです:

    AnyList sumList;
sumList = mylist + mylist2;
sumList.print();

print 関数に入り、関数 getData() からデータを返そうとすると、不正なアクセス エラーが発生します。

なぜこれが事実なのか、私にはまったくわかりません。どんな助けでも大歓迎です!

ありがとう!

4

4 に答える 4

3

mylist + mylist2完全な式の最後でデストラクタが呼び出される一時的なものを作成します。代入演算子は浅いコピーを行うため、一時的なデストラクタが呼び出されてメモリが解放されると、sumListダングリング ポインタが発生します。

ディープコピーを行う方法を読んでください。

これをテストするために、デストラクタを一時的に削除できます。ただし、テストするだけです。リソースを管理している場合は必要になります。

于 2013-01-29T17:07:15.280 に答える
1

このコード

AnyList sumList = mylist + mylist2;

ではなくコピー コンストラクターを呼び出しますoperator=(コピーの初期化を参照) 。

この

sumList = mylist + mylist2;

確かに電話operator=

ほとんどの場合、コピー コンストラクターはディープ コピーを実行しますが、これは正しく、クラッシュには至りません。浅いoperator=コピーを行うと、結果としてクラッシュが発生します

于 2013-01-29T17:09:59.307 に答える
0

代入演算子は、他のリストから「最初の」ポインターをコピーするため、両方のリストが同じノードを共有することになります。(オペレーターのループは、各ノードのデータにそれ自体へのポインターを割り当てているため、何もしないための長い道のりです)。おそらく、リストにはノードを削除するデストラクタがあるため、両方のリストが同じノードを削除しようとすることになります。したがって、エラー (またはその他の未定義の動作) です。

リストをコピー可能にして割り当て可能にしたい場合は、おそらく良い考えではありませんが、「ディープ」コピーを実行して、割り当て先リストの新しいノードを作成する必要があります。また、ポインタをそれらに再割り当てする前に、古いノードを削除することを忘れないでください。

リンク リストの実装方法を学んでいない場合は、標準ライブラリが提供するコンテナーを使用してください。

于 2013-01-29T17:11:27.733 に答える
0

あるケースではエラーが発生し、別のケースではエラーが発生しないのはなぜですか? = 演算子を呼び出さず、代わりにコピー コンストラクターを呼び出すためAnyList sumList = mylist + mylist2; です。一方

AnyList sumList;
sumList = mylist + mylist2;

デフォルトのコンストラクターを呼び出してから、= 演算子を呼び出します。

operator= を使用するとクラッシュする理由を確認するのに十分なコードを示していませんが、ルシアン・グリゴレの答えにはおそらくその権利があることをお勧めします。

于 2013-01-29T17:10:58.700 に答える