【发布时间】:2020-07-26 00:43:17
【问题描述】:
我正在用 C++ 实现一个链接的字符串堆栈,主要是为了好玩。列表的每个对象都是Node 的实例化,而列表本身是StackOfStrings 的实例。现在我使用new 实例化一个新的Node 并且一切正常,但我似乎无法弄清楚如何在堆栈上实例化Node 并在稍后的代码中引用它。
我尝试在 push() 方法中将 first = new Node; 更改为 first = &Node();,但是当我调用 pop() 方法时出现运行时 std::bad_alloc 错误。我的猜测是,这个Node 在堆栈上创建,并在程序退出push() 方法后立即销毁。所以我的问题是:有没有一种方法可以创建分配给first 在堆栈上创建的Node 并保留它以供以后使用?
我包含了代码的基本内容,我在导致我出现问题的行旁边添加了注释。
class StackOfStrings
{
public:
StackOfStrings() {}; // Could be omitted, default constructor
void push(std::string item)
{
Node* old_first = first;
first = new Node; // *** my question revolves around this line ***
// *** "first = &Node()" does not work ***
// *** how can I have a Node on the stack? ***
first->setItem(item);
first->setNext(old_first);
}
std::string pop()
{
std::string item = first->getItem();
first = first->getNext();
return item;
}
private:
Node *first = nullptr;
};
为了完整起见,这是Node 类:
class Node
{
public:
std::string getItem() { return item; }
Node* getNext() { return next; }
void setItem(std::string item) { this->item = item; }
void setNext(Node *node) { this->next = node; }
private:
std::string item;
Node* next = nullptr;
};
编辑:我错误地写了 *Node 而不是 &Node。我更新了问题。
编辑 2:我尝试的一个小实验:
- 我调用了
StackOfStrings的push()方法在链表中插入单词“hello”。 - 在
Node的setItem()方法中插入了一个断点,以检查世界“hello”是否保存在内存中。确实,在内存地址0x00FFF900,我找到了值68 65 6c 6c 6f,对应于ASCII中的“hello” - 然后我在对
getItem()的调用中放置了另一个断点,以便再次分析相同的内存地址。我现在发现a0 fb ff 00 28是垃圾,当然不是“你好”。
【问题讨论】:
-
不,堆栈是临时的,它上面的任何值在你的函数结束时都变得无效。为什么要使用栈而不是堆?
-
@AlanBirtles 谢谢。真的没有什么特别的原因,我只是想看看是否有可能以某种方式做到这一点。
-
@giacomo-b 你能告诉我们实际的错误吗?为什么要在堆栈上分配 Node 对象(正如@AlanBirtles 提到的堆栈变量在函数末尾被销毁)。语法
first = *Node()不是有效的 C++ 语法。 -
下次调用例程时,它会将该堆栈内存用于其他用途。这就是堆栈的工作原理。
-
@giacomo-b “我现在发现的 a0 fb ff 00 28 是垃圾,当然不是“你好”。”。如前所述,这是因为局部变量在函数退出并释放内存时被破坏。如果您有一些问题要尝试以这种方式解决,那么我认为您需要提供有关该问题的更多信息(XY problem),也许我们可以帮助您找到正确的解决方案,否则在堆栈上分配变量并使用它们当堆栈框架被销毁是一个非常糟糕的主意,我认为你无法让它工作。
标签: c++ pointers stack new-operator heap-memory