c++中栈分配数据的生命周期

Life span of stack allocated data in c++

本文关键字:生命 周期 数据 分配 c++      更新时间:2023-10-16

我有c++代码在Debian (gcc (Debian 4.7.2-5) 4.7.2)中正常工作,但在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);

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

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

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

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

是的。

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

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

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

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

保证walker会在访问者之前被销毁,所以即使在析构函数中也不会包含任何悬垂引用

Visitor1()不是一个局部变量,它是一个临时变量。当出现临时对象的完整表达式结束时,临时对象的生存期结束。

如果你需要保存它们,使用局部变量代替临时变量。