我几周前才开始学习C ++。因此,现在我有一个学校分配问题,要求我在不使用“新”或与动态分配内存有关的任何情况下实现链接列表(并且不能使用STL中的任何ADT)。教授说,一切都可以在堆栈上完成,但是怎么办呢?从周五开始,我一直在从事此工作,但仍然没有运气。
它说:保留一堆正在读取的文件名。对堆栈使用以下数据结构:
struct Node {
string fileName;
Node *link;
};
我试图避免使用new,但是当我将列表的头传递给递归方法调用时,它总是给我“ segmentation fault”或“ BUS error”。关于如何解决此问题的任何想法?
堆和栈之间的区别主要是(不仅是,主要是出于这个问题的缘故)在哪里分配内存以及如何释放内存。当您要在堆上分配节点时,说new Node
,系统将为您提供内存,跟踪使用了哪些块以及哪些块是空闲的,并为您提供了一次释放块的方法您不再需要它。
但是您也可以在堆栈的数组中拥有一个节点池。 (自动变量是堆栈变量。)您可以从该池中“分配”,跟踪使用了阵列中的哪些节点以及哪些节点是空闲的,并将未使用的节点标记为不再需要的空闲节点。但是,由于数组的大小在编译时是固定的,所以这意味着列表的最大长度。
我创建了一个小样本,您可能会从中发现启发。我在堆栈上创建了一个单链元素列表。请注意,该列表是如何反向创建的,以及如何使用递归来“分配”所需的主题的数量。还要注意如何将列表作为参数传递给。希望这会有所帮助,祝你好运。
#include <cstdio>
using namespace std;
struct Node {
Node* next_;
int value_;
};
// Creates a linked list of nodes containing raising values.
void intList(Node* prevNode, int restValue) {
if (restValue) {
// A node on the stack, which is linked to list created so far.
Node node;
node.next_ = prevNode;
node.value_ = restValue;
// Create a next node or print this list if rest runs to zero.
intList(&node, restValue - 1);
}
else {
// Depest recursion level, whole list is complete.
for (Node* iter = prevNode; iter; iter = iter->next_)
printf("item %d\n", iter->value_);
}
}
int main() {
intList(NULL, 10);
}
一旦调用一个函数,该函数的堆栈分配就是固定的。
获取更多分配的堆栈内存的唯一方法是调用另一个函数。然后可以调用另一个函数。然后可以调用另一个函数。也许它们都可能具有相同的功能...
每个函数调用都有自己的固定大小的堆栈,但是函数调用图本身是这些堆栈的可变大小的堆栈。
您可能应该与您的教授讨论并澄清要求,因为从您的描述来看,这对于新的c ++程序员来说似乎是非常奇怪的任务。至少可以说,要求实现仅在堆栈上具有内存的链表的实现。
想想数组。如果需要,可能不止一个。
没有太多信息:
使用alloca()
而不是malloc()
函数可以在调用者函数的堆栈帧而不是堆上动态分配内存。您不必担心释放内存,因为当函数返回时它会自动释放。
如果知道需要存储多少文件名,则可以使用struct Node数组并从中构建列表。
要“在堆栈上创建一个链表”,通常使用alloca之类的函数来获取更多的堆栈内存。但是,这听起来不像您要执行的操作。
可以使用C ++ 运算符的地址