实现模板化单链表时遇到问题
Trouble implementing a templated singly linked list
我正在尝试实现一个模板化的单向链表,我对 C++ 还很陌生
#include <iostream>
#include <string>
#define NEWL "\n"
#define PRINT(s) std::cout << s
#define PRINTL(s) std::cout << s << NEWL
#define PRINTERR(e) std::cerr << e << NEWL
////// Class for a Node
template<class Data> class Node {
Node<Data>* next_ptr;
Data data;
public:
Node(Node<Data>* nxt_ptr) :next_ptr(nxt_ptr) {};
Node(Data d, Node<Data>* nxt_ptr) :data(d), next_ptr(nxt_ptr) {};
Node<Data>* get_next() { return next_ptr; }
Data& get_data() { return data; }
friend std::ostream& operator<<(std::ostream& out, const Node<Data>& node) {
out << node.data;
return out;
};
};
////// Class for a SinglyLinkedList
template<class Data> class SLinkedList {
Node<Data>* head_ptr;
int max_size;
public:
SLinkedList() : head_ptr(nullptr) {};
bool is_empty() {
return head_ptr == nullptr;
};
bool is_full() {
return get_size() == max_size;
};
int get_size() {
if (is_empty()) {
return 0;
}
int count = 0;
for (Node<Data>* it_ptr = head_ptr; it_ptr != nullptr; it_ptr = it_ptr->get_next()) {
count++;
}
return count;
};
void add(Data d) {
if (is_full()) {
throw std::exception("List is full!");
}
Node<Data> new_node(d, head_ptr);
head_ptr = &new_node;
};
void print_content() {
int count = 1;
PRINTL("This list contains:");
for (Node<Data>* it_ptr = head_ptr; it_ptr != nullptr; it_ptr = it_ptr->get_next()) {
PRINTL("\t["<< count << "]" << " at " << it_ptr << " : " << *it_ptr);
count++;
}
}
};
////// Main function
int main()
{
SLinkedList<int> sll;
sll.add(42);
sll.print_content();
}
我无法让它工作。不知何故用 for 循环迭代列表不起作用。它总是导致关于指向 0xCCCCCCD0
的指针的读取访问冲突异常,我不知道如何解决这个问题。
你的add
函数不正确
Node<Data> new_node(d, head_ptr);
在 add
中创建一个新的本地函数 Node
。然后将 head
设置为该局部变量的地址。当函数结束时,所有局部变量都被销毁,所以现在 head
指向一个不再存在的对象。
要解决此问题,您需要使用 new
关键字创建一个动态对象,该对象将在函数结束后继续存在。
Node<Data>* new_node = new Node(d, head_ptr);
head_ptr = new_node;
这样做的缺点是您需要记住在列表析构函数中创建的所有节点上调用 delete
。
您的代码中还有其他一些错误。你永远不会在你的构造函数中设置 max_size
所以除了给它一个值之外使用它是未定义的行为,因为我们不知道它的值是什么。将节点添加到列表中时,您也永远不会增加列表的大小。
我正在尝试实现一个模板化的单向链表,我对 C++ 还很陌生
#include <iostream>
#include <string>
#define NEWL "\n"
#define PRINT(s) std::cout << s
#define PRINTL(s) std::cout << s << NEWL
#define PRINTERR(e) std::cerr << e << NEWL
////// Class for a Node
template<class Data> class Node {
Node<Data>* next_ptr;
Data data;
public:
Node(Node<Data>* nxt_ptr) :next_ptr(nxt_ptr) {};
Node(Data d, Node<Data>* nxt_ptr) :data(d), next_ptr(nxt_ptr) {};
Node<Data>* get_next() { return next_ptr; }
Data& get_data() { return data; }
friend std::ostream& operator<<(std::ostream& out, const Node<Data>& node) {
out << node.data;
return out;
};
};
////// Class for a SinglyLinkedList
template<class Data> class SLinkedList {
Node<Data>* head_ptr;
int max_size;
public:
SLinkedList() : head_ptr(nullptr) {};
bool is_empty() {
return head_ptr == nullptr;
};
bool is_full() {
return get_size() == max_size;
};
int get_size() {
if (is_empty()) {
return 0;
}
int count = 0;
for (Node<Data>* it_ptr = head_ptr; it_ptr != nullptr; it_ptr = it_ptr->get_next()) {
count++;
}
return count;
};
void add(Data d) {
if (is_full()) {
throw std::exception("List is full!");
}
Node<Data> new_node(d, head_ptr);
head_ptr = &new_node;
};
void print_content() {
int count = 1;
PRINTL("This list contains:");
for (Node<Data>* it_ptr = head_ptr; it_ptr != nullptr; it_ptr = it_ptr->get_next()) {
PRINTL("\t["<< count << "]" << " at " << it_ptr << " : " << *it_ptr);
count++;
}
}
};
////// Main function
int main()
{
SLinkedList<int> sll;
sll.add(42);
sll.print_content();
}
我无法让它工作。不知何故用 for 循环迭代列表不起作用。它总是导致关于指向 0xCCCCCCD0
的指针的读取访问冲突异常,我不知道如何解决这个问题。
你的add
函数不正确
Node<Data> new_node(d, head_ptr);
在 add
中创建一个新的本地函数 Node
。然后将 head
设置为该局部变量的地址。当函数结束时,所有局部变量都被销毁,所以现在 head
指向一个不再存在的对象。
要解决此问题,您需要使用 new
关键字创建一个动态对象,该对象将在函数结束后继续存在。
Node<Data>* new_node = new Node(d, head_ptr);
head_ptr = new_node;
这样做的缺点是您需要记住在列表析构函数中创建的所有节点上调用 delete
。
您的代码中还有其他一些错误。你永远不会在你的构造函数中设置 max_size
所以除了给它一个值之外使用它是未定义的行为,因为我们不知道它的值是什么。将节点添加到列表中时,您也永远不会增加列表的大小。