Override = operator linked linked c++ deep copy

£可爱£侵袭症+ 提交于 2019-12-13 04:24:37

问题


So, I'm trying override operator= in a linked list class I'm writing, but keep getting this weird problem for some reason.

List& List::operator=(const List& copyList){
if(copyList.head != nullptr){
    makeEmpty();   // clears *this from any previous nodes
    cout << "if statement " << endl;
    head = new Node; // create a new node for head
    head -> data = copyList.head -> data; // copy the first data of copylist
    Node* pnew = head; // a temp node to traverse the new linkedlist
    assert(head != nullptr);
    Node* current2 = copyList.head;
    current2 = current2 -> next;
    while(current2 != NULL && pnew != NULL){
        cout << "entering while loop " << endl;
        pnew-> next = new Node;
        pnew -> next->data = current2 ->data;
        cout << "pnew next data " << *(pnew -> next->data)  << endl;
        assert(pnew-> next != nullptr);
        pnew = pnew -> next;
        current2 = current2 -> next;
        cout << "after current2" << endl;
    }
     pnew -> next = NULL;

}else{
    cout << "else statement " << endl;
    head = nullptr;
}
cout<< "printing out copylist"<< endl << copyList << endl;
cout<< "printing current list: " << endl << *this << endl;
return *this;

}

So, this is the code I have to test the operator override:

cout << "mylist:" << endl << mylist << endl;
   cout << "mylist4:" << endl << mylist4 << endl;
   mylist = mylist4;
   cout << "mylist:" << endl;
   cout << mylist << endl;
   cout << "mylist4:" << endl;
   cout << mylist4 << endl;

This is the output:

mylist:
10 f
16 u
20 n
25 !

mylist4:
14 s
15 t
16 u
18 f
19 f
25 !

if statement
entering while loop
pnew next data 15 t

after current2
entering while loop
pnew next data 16 u

after current2
entering while loop
pnew next data 18 f

after current2
entering while loop
pnew next data 19 f

after current2
entering while loop
pnew next data 25 !

after current2
printing out copylist
14 s
15 t
16 u
18 f
19 f
25 !

printing current list:
14 s
15 t
16 u
18 f
19 f
25 !
*crashes right here*

I have been trying to figure out this problem for about 3 days. Any help would be highly appreciated. Thanks in advance!

EDIT: here are the constructor (the destructor is the default one by the compiler):

NodeData::NodeData(int n, char c)  { 
    num = n; ch = c; 
} 

EDIT2: I found the problem after careful examination. The problem was that I did not point the last node of head, pnew after the while loop, to null. This fixed the issue. Thanks to all your support.


回答1:


You have control over your Node class, and it should support copy-construction and assignment operators either transparently or if needed by your own hand. Given that, I concur with Dietmar that utilizing the copy-ctor/swap/destructor mechanics is the ideal approach.

If you insist on doing this by-hand the following is one way to do it. Your implementation is making this much harder than it needs to be.

List& List::operator=(const List& copyList)
{
    List tmp;
    Node **dst = &tmp.head;
    const Node* src = copyList.head;
    while (src)
    {
        *dst = new Node(*src);     // invoke Node copy-ctor
        src = src->next;           // advance source
        (*dst)->next = nullptr;    // break link to original next
        dst = &(*dst)->next;       // move target to next pointer
    }

    // tmp now has a copy of the source list
    //  swap its head pointer with ours.
    std::swap(tmp.head, head);

    // upon return, the tmp object that now holds our
    //  original list will clean it up. we own the
    //  new list form this point on. 
    return *this;
}

How It Works

The pointer-to-pointer dst always holds the address of the next pointer to be populated with a new node. Initially it holds the address of the local List tmp object's head pointer. . As we add nodes it is updated to always hold the address of the next pointer of the last-node-added. By doing this we get forward-chaining automatically. Once we're done copying, tmp is now a duplicate of the source. We then swap head pointer with own own. This in turn swaps who owns which list. When tmp is destroyed on function-exit it will destroy our old list with it. We keep the new list, pointed to by our head pointer.

The above assumes you're using the default copy-ctor of Node, which means making a copy will copy both the data value and the next link, the latter you do NOT want, thus the embedded link-break. If you actually implement Node::Node(const Node&) to always set the link to NULL after the copy the link-break can be eliminated. I.e., your Node copy-constructor should look something like this:

Node::Node(const Node& arg)
    : data(arg.data)
    , next()
{
}

This ensures a clean(as clean as data can be copied, anyway) copy with no accidental link to the original arg next pointer.

All of that said, Dietmar's answer is the most-correct, and I've up voted it accordingly. If this helps you, consider up-voting it, but his is easily the ideal solution.




回答2:


Without looking to hard at the implementation (I stopped when I spotted makeEmpty() which makes sure that the assignment operator won't be strongly exception-safe without any good reason): the easiest way to implement an assignment operator is to leverage the copy constructor, the destructor, and a generally trivial to write swap() funciton. The implementation look the same for all classes except for the class name:

T& T::operator= (T other) {
    other.swap(this);
    return *this;
}

Note, it is deliberate to pass the argument by value: this is where the value is actually happening. Compared to copying by T const& it has the advantage the actual copy can be elided in some cases.



来源:https://stackoverflow.com/questions/19610604/override-operator-linked-linked-c-deep-copy

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!