如何访问调用堆栈?

时间:2012-04-23 11:38:19

标签: c++ callstack

我有一个由父节点和子节点组成的树数据结构,如下所示:

<Node1>
  <Node2/>

  <Node3>
    <Node4/>
  </Node3>
</Node1>

要解析结构,我使用μ递归函数:

void RecursiveFunction(NodeT node)
{
    if(node.has_child())
        RecursiveFunction(node.child());
}

当我调用RecursiveFunction作为参数传递时,例如,Node2我希望能够访问父(Node1)数据而不使用其他数据结构存储这些数据,因为第一个节点的数据已存储在调用中在进行递归调用之前进行堆栈。因此,当我解析Node2无法直接访问父亲时,我需要访问调用堆栈以读取Node1的数据,依此类推。

例如,如果我正在解析Node4:

void RecursiveFunction(NodeT node)
{
    /* Access to Node3 and Node1 data...

    if(Node4.has_child())
        RecursiveFunction(Node4.child()); */
}

有可能吗?以什么方式?

感谢。

5 个答案:

答案 0 :(得分:1)

这是可能的,但这样做会非常危险。这主要是因为你想搞乱进程堆栈。另外我认为没有任何库函数可以这样做,据说你必须做一些指针算术才能实现这一点。

答案 1 :(得分:1)

即使你找到了一种从调用函数访问数据的方法,任何其他程序员都不容易理解你的工作。

我建议通过迭代替换递归,这应该允许您清楚地表达您想要做的事情。有关详细信息,请参阅Way to go from recursion to iteration

答案 2 :(得分:1)

访问callstack对我来说有点过度工程。将函数从递归转换为迭代并使用您自己的堆栈。堆栈应包含一个NodeT实例和通知函数的整数值,已经处理了多少个节点的子节点。如果此值低于节点的子计数,则循环将递增此值并将下一个子项添加到堆栈。否则它将处理该节点,然后从堆栈中弹出它。

另一个优点是,您不再受程序堆栈大小的限制,如果有这样的需要,您可以处理更多嵌套结构。否则你冒险,好吧,让我们不要害怕说,堆栈溢出。

答案 3 :(得分:0)

如果您想要或必须(例如家庭作业?)坚持递归,请将父节点作为第二个参数添加到您的函数中,默认为NULL,表示当前节点是根节点。即:

void RecursiveFunction(NodeT const& node, NodeT const* parentPtr=NULL)
{
    if(node.has_child())
        RecursiveFunction(node.child(), &node);
}

请注意,我修改了你的函数以通过引用const来接受第一个参数,否则你会创建一个 lot 的树副本。

答案 4 :(得分:0)

调用堆栈也用于函数参数*,因此使用它来构建链:

struct chain {
  NodeT* node;
  chain const* parent;
}
void RecursiveFunction(chain const& c)
{
    if(c.node->has_child()) {
       chain child = { c.node->child(), &c };
        RecursiveFunction(child);
    }
}

[*]至少在概念上;实际实施可能不同。无论如何,这个C ++代码是可移植的,与低级别的黑客不同。