2

我有在 Debian (gcc (Debian 4.7.2-5) 4.7.2) 中正常工作的 c++ 代码,但在 Ubuntu (gcc (Ubuntu/Linaro 4.7.2-2ubuntu1) 4.7.2) 中失败。我正在变量之间重用堆栈空间,类似于这些问题中描述的内容:

在 C 中,大括号是否充当堆栈框架?

C++ 堆栈和作用域

除了我没有嵌套范围。相反,代码看起来类似于:

TreeWalker walker;
walker.addVisitor(nodeType1, Visitor1());
walker.addVisitor(nodeType2, Visitor2());
...
walker.walkTree(tree);

我可以通过在堆上分配来缓解这个问题,但我想知道我能做些什么来确保局部变量留在原地?将访问者分配给局部变量是否足以确保它们不会被重用?在函数代码中最后一次使用堆栈变量后,标准是否对堆栈变量提供了任何承诺?

4

2 回答 2

4

我能做些什么来确保局部变量留在原地?

要么使用(命名的)局部变量,而不是临时变量;或修改addVisitor以存储访问者的副本而不是对其的引用,如果可行的话。

将访问者分配给局部变量是否足以确保它们不会被重用?

是的。

在函数代码中最后一次使用堆栈变量后,标准是否对堆栈变量提供了任何承诺?

临时对象(在表达式期间创建的未命名对象,例如您创建的访问者)一直存在到创建它们的完整表达式结束。所以它们一直持续到调用addVisitor返回,但在下一行之前被销毁。

局部变量(在代码块中声明的自动变量)一直持续到程序离开声明它们的最里面的块。发生这种情况时,该块中的每个局部变量都会按照其声明的相反顺序销毁。所以在下面:

{
    Visitor1 visitor1;
    Visitor2 visitor2;
    TreeWalker walker;
    walker.addVisitor(nodeType1, visitor1);
    walker.addVisitor(nodeType2, visitor2);
    //...
    walker.walkTree(tree);
}

它保证walker会在访问者之前被销毁,因此即使在其析构函数中也不会包含任何悬空引用。

于 2013-05-07T08:09:18.253 回答
2

Visitor1()不是局部变量,而是临时变量。临时的生命周期在它出现的完整表达式结束时结束。

如果您需要保留它们,请为它们使用局部变量而不是临时变量。

于 2013-05-07T07:59:19.457 回答