我正在编写一个类,该类将用作 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)中。
段错误的原因究竟是什么?为什么此代码在复制构造函数期间失败,但在以其他方式调用时则不失败?
我认为你把它复杂化了,你可以在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;
}
这不会检查空头,因此您可能需要添加该逻辑