我正在编写一个类,它将作为Student对象的单链表的容器(自定义类,其规范无关紧要)。除了复制构造函数之外,它功能完备(我可以轻松添加和删除节点)。使用我的复制构造函数,我的目标是只复制列表的数据(即不是指针本身),但由于某种原因它会出现段错误。
以下是相关代码(注释用注释来解释不明确的部分):
LinkedList::LinkedList(const LinkedList& copy) {
Student s = copy.head->getStudent();
//Node can be initialized with a Student pointer argument
head = new Node(new Student(s.getFirstName(), s.getMiddleInitial(),s.getLastName(),s.getSSN(),s.getAge()));
Node *curr = copy.head->getNext();
Node* prev = head; //For saving the tail
while(curr != NULL){
Student s = curr->getStudent();
append(s);
prev = curr;
curr = curr->getNext();
}
tail = prev;
cout << "Leaving method..." << endl;
}
//Irrelevant methods omitted
void LinkedList::append(Node*& n) {
cout << "Got to appending to node obj" << endl;
if (head == NULL) {
head = tail = n;
} else {
tail->setNext(n);
tail = tail->getNext();
}
}
void LinkedList::append(Student s) {
Node* n = new Node(s.getFirstName(),s.getMiddleInitial(),s.getLastName(),s.getSSN(),s.getAge());
append(n);
}
//From Node.cpp
void Node::setNext(Node* _next) {
next = _next; //Next is a Node pointer (i.e. Node*)
}
我想强调一下,添加到原始列表时此代码可以正常工作。只有在复制构造函数中,此代码才会失败。我通过Valgrind运行此代码,我收到以下错误:
==23990== Invalid write of size 8
==23990== at 0x403018: Node::setNext(Node*) (Node.cpp:86) //This is the "next = _next" line
==23990== by 0x402694: LinkedList::append(Node*&) (LinkedList.cpp:81)
==23990== by 0x402371: LinkedList::append(Student) (LinkedList.cpp:90)
==23990== by 0x401F68: LinkedList::LinkedList(LinkedList const&) (LinkedList.cpp:31)
这使我感到困惑,因为指针是(并且应该是)大小为8,被保存到指针(大小为8)。
段错的原因究竟是什么?为什么这个代码在复制构造函数期间失败但在被调用时却没有?
答案 0 :(得分:1)
我认为你已经过度复杂了,你可以在while循环中完成它:
LinkedList::LinkedList(const LinkedList& copy) {
Student s = copy.head->getStudent();
//Node can be initialized with a Student pointer argument
head = new Node(new Student(s.getFirstName(),s.getMiddleInitial(),s.getLastName(),s.getSSN(),s.getAge()));
Node *curr = copy.head->getNext();
Node *newListCur = head;
Node* prev = head; //For saving the tail
while(curr != NULL){
Student s = curr->getStudent();
//important step
Node* newNode = new Node(new Student(s.getFirstName(),s.getMiddleInitial(),s.getLastName(),s.getSSN(),s.getAge()));
newListCur->setNext(newNode);
//
newListCur = newListCur->getNext();
curr= curr->getNext();
}
cout << "Leaving method..." << endl;
}
这不会检查NULL头,因此您可能需要添加该逻辑