[英]Doubly linked list insert method
我目前正在做一項學習雙向鏈表和迭代器的作業。 我正在制作一個insert()
方法,它接受迭代器類型以及要添加到列表中的數據。 但是,我在insert()
方法中標記的那一行出現異常,它說:
拋出異常:讀取訪問沖突。 iter.node 是 0xFFFFFFFFFFFFFFEF
我不確定這是迭代器還是鏈表的問題:
#include <cstdlib>
#include <iostream>
using namespace std;
class List {
struct Node {
int data;
Node* next = nullptr;;
Node* prev = nullptr;
};
friend ostream& operator<<(ostream& os, const List& rhs);
public:
class iterator {
friend class List;
Node* node = nullptr;
public:
iterator(Node* node) : node(node) {}
iterator& operator++() {
node = node->next;
return *this;
}
iterator& operator--() {
node = node->prev;
return *this;
}
bool operator==(const iterator& rhs) {
if (node != rhs.node) {
return false;
}
return true;
}
bool operator!=(const iterator& rhs) {
return !(*this == rhs);
}
int operator*() const {
return node->data;
}
iterator& operator->() {
return *this;
}
};
List() {
header = new Node();
trailer = new Node();
header->next = trailer;
header->prev = nullptr;
trailer->prev = header;
trailer->next = nullptr;
}
void push_back(int data) {
Node* newNode = new Node();
newNode->data = data;
newNode->prev = trailer->prev;
newNode->prev->next = newNode;
newNode->next = trailer;
trailer->prev = newNode;
}
void pop_back() {
Node* tempNode = trailer->prev->prev;
tempNode->next = trailer;
trailer->prev = tempNode;
}
void push_front(int data) {
Node* newNode = new Node();
newNode->data = data;
header->next->prev = newNode;
newNode->next = header->next;
newNode->prev = header;
header->next = newNode;
}
void pop_front() {
Node* tempNode = header->next->next;
tempNode->prev = header;
header->next = tempNode;
}
int& front() {
if (header->next == trailer) {
cerr << "List is empty" << endl;
}
return header->next->data;
}
int& back() {
if (trailer->prev == header) {
cerr << "List is empty" << endl;
}
return trailer->prev->data;
}
int front() const {
if (header->next == trailer) {
cerr << "List is empty" << endl;
}
return header->next->data;
}
int back() const {
if (trailer->prev == header) {
cerr << "List is empty" << endl;
}
return trailer->prev->data;
}
int size() const {
int count = 0;
for (iterator i = begin(); i != end(); ++i) {
++count;
}
return count;
}
int& operator[](int index) {
int ind = 0;
for (iterator i = begin(); i != end(); ++i) {
if (ind == index) {
return i.node->data;
}
++ind;
}
}
int operator[](int index) const {
int ind = 0;
for (iterator i = begin(); i != end(); ++i) {
if (ind == index) {
return i.node->data;
}
++ind;
}
}
iterator& begin() {
iterator iter(header->next);
return iter;
}
iterator& end() {
iterator iter(trailer);
return iter;
}
iterator begin() const {
iterator iter(header->next);
return iter;
}
iterator end() const {
iterator iter(trailer);
return iter;
}
iterator& insert(iterator& iter, int data) {
Node* newNode = new Node();
newNode->data = data;
iter.node->prev->next = newNode; //exception is thrown on this line
newNode->prev = iter.node->prev;
newNode->next = iter.node;
iter.node->prev = newNode;
iterator newIter(newNode);
return newIter;
}
void clear() {
Node* iter = header->next;
Node* next;
while (iter != trailer) {
next = iter->next;
delete iter;
iter = nullptr;
iter = next;
}
header->next = trailer;
trailer->prev = header;
}
iterator& erase(iterator& iter) {
for (iterator i = ++begin(); i != end(); ++i) {
if (i == iter) {
Node* tempNode = i.node;
tempNode->prev->next = tempNode->next;
tempNode->next->prev = tempNode->prev;
delete tempNode;
tempNode = nullptr;
return ++i;
}
}
}
public:
private:
Node* header;
Node* trailer;
};
ostream& operator<<(ostream& os, const List& rhs) {
for (int i : rhs) {
os << i << " ";
}
os << endl;
return os;
}
void printListInfo(const List& myList) {
cout << "size: " << myList.size()
<< ", front: " << myList.front()
<< ", back(): " << myList.back()
<< ", list: " << myList << endl;
}
int main() {
List myList;
for (int i = 0; i < 10; ++i) myList.insert(myList.end(), i * i);
printListInfo(myList);
myList.clear();
for (int i = 0; i < 10; ++i) myList.insert(myList.begin(), i * i);
printListInfo(myList);
}
iterator& iterator::begin()
和iterator& iterator::end()
返回對局部變量的引用。 由於正是這些函數通過myList.insert(myList.begin(), ..)
等傳遞給 main 中的List::insert(...)
,因此插入 function 總是在無效的迭代器上運行。
類似地, iterator::insert
有一個類似的問題,它通過引用返回局部變量:
iterator& insert(...)
{
...
iterator newIter(newNode);
return newIter;
}
一旦這些函數退出,局部變量將被銷毀,因此返回的那些引用將懸空 - 指向 memory,而 object 曾經是。
一個快速修復方法是確保這些新迭代器不是 function 的本地迭代器,而是在堆上初始化,例如
iterator& begin() {
iterator* iter = new iterator(header->next);
return *iter;
}
iterator& end() {
iterator* iter = new iterator(trailer);
return *iter;
}
但是,這也意味着您必須引入一種方法來跟蹤這些迭代器,以便在不再需要迭代器時可以釋放 memory,可能是通過將迭代器存儲為List
的成員變量而不是存儲 begin /end List
的Node
s,因此只能通過iterator
s 訪問Nodes
。
我發現這是由於編譯時帶有警告,強烈推薦!
In member function 'List::iterator& List::begin()':
<source>:151:16: warning: reference to local variable 'iter' returned [-Wreturn-local-addr]
151 | return iter;
| ^~~~
<source>:150:18: note: declared here
150 | iterator iter(header->next);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.