覆盖=运算符链接的链接C ++深度复制 [英] Override = operator linked linked c++ deep copy

查看:78
本文介绍了覆盖=运算符链接的链接C ++深度复制的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此,我正在尝试在我正在写的链表类中重写operator =,但是由于某种原因,总是遇到这个奇怪的问题.

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;

这是输出:

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*

我已经尝试解决此问题大约3天了.任何帮助将不胜感激.提前致谢!

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

这是构造函数(析构函数是编译器默认的构造函数):

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

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

经过仔细检查,我发现了问题.问题是我没有将head的最后一个节点(在while循环之后的pnew)指向空.这解决了问题.感谢您的支持.

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.

推荐答案

您可以控制Node类,它应该透明地或在您自己需要的情况下支持复制构造和赋值运算符.鉴于此,我同意Dietmar的观点,即利用copy-ctor/swap/destructor机制是理想的方法.

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;
}

工作原理

指针到指针dst始终保存要用新节点填充的下一个指针的地址.最初,它保存本地List tmp对象的头指针的地址. .当我们添加节点时,将对其进行更新以始终保留最后添加的节点的next指针的地址.这样,我们就可以自动进行正向链接.复制完成后,tmp现在是源的副本.然后,我们将自己的头指针互换.这反过来交换谁拥有哪个列表.当tmp在函数退出时被破坏时,它将随之破坏我们的旧列表.我们保留由head指针指向的新列表.

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.

以上假设您使用默认的Node复制代码,这意味着进行复制将复制数据值下一个链接,后者是您不希望的,因此嵌入式链接中断.如果实际上实现了Node::Node(const Node&),以便在复制后始终将链接设置为NULL,则可以消除链接中断.也就是说,您的Node复制构造函数应如下所示:

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()
{
}

这可确保进行干净的复制(无论如何都可以复制data),并且不会意外链接到原始的arg下一个指针.

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

所有这些都说明,Dietmar的答案是最正确的,因此我对此进行了投票.如果这对您有帮助,请考虑对其进行投票,但他的选择很容易成为理想的解决方案.

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.

这篇关于覆盖=运算符链接的链接C ++深度复制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆