覆盖=运算符链接的链接C ++深度复制 [英] Override = operator linked linked c++ deep copy
问题描述
因此,我正在尝试在我正在写的链表类中重写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屋!