C++本地变量销毁顺序

82
在C++(11)中,局部变量的销毁顺序是否被定义?更简洁地说,在同一范围内两个局部变量的析构函数的副作用将按照何种顺序变得可见?
例如:
struct X{
  ~X(){/*do something*/}
}

int main(){
   X x1;
   X x2;
   return 0;
}

当主函数返回时,x1x2哪个会先被销毁,或者在C++11中顺序是否未定义?

6个回答

93

在每个存储类别中(除了动态分配的对象),对象的销毁顺序是按照构造顺序的相反顺序进行的。


8
C++标准中的哪个部分保证了这个顺序? - David Grayson
28
每个类别都有不同的部分。对于具有线程本地或静态存储的对象,请参见§3.6.3。关于具有自动生存期的对象,请参阅§6.6(这并不是人们可能希望查找它的地方)。对于类成员和基类,请参见§12.4/8。关于临时对象,请参阅§12.2。 - James Kanze
19
由于当引用直接绑定一个临时对象时,会延长其生命周期,因此临时对象不严格遵循LIFO顺序。 - Ben Voigt
@BenVoigt 低估了这条评论。 - UmNyobe

31

I. 关于本地变量

  1. 本地变量分配在上。

  2. 基于后进先出(LIFO)的模式。

  3. 因此,变量按照分配和构造的反向顺序被销毁和释放。

II. 关于您的示例

调用您的函数 main():

  • x1 被分配并构造在 上,
  • x2 被分配并构造在

当达到 main() 函数范围的结尾时:

  • x2 中被销毁和释放,
  • x1 中被销毁和释放

III. 此外

看起来像这样:

(使用方案更容易理解的行为)

Stack scheme


2
虽然我不反对这张图片,但实现已经过时了,已经很久没有使用了push/pop操作。相反,它执行一个 sub %esp, <size> 操作来分配所有必要的空间,并在退出时执行 add %esp, <size> 操作。因此,换句话说,所有必要的空间都是一次性分配的(只有 alloca() 才会动态地进一步减少栈指针)。 - Alexis Wilke
8
这个问题与堆栈的存在或事物在其中分配的方向无关,而与词法作用域被按它们建立的相反顺序舍弃有关。对象x1x2可以以任何顺序分配在栈帧中,甚至可能不被分配;例如,它们可以是空结构体。 - Kaz
3
@AlexisWilke 神奇!在短短几秒内,有几条评论与2014年回答的类似。 - Kaz

8

这是一种 栈数据结构 行为,所以局部变量存储在栈中作为 LIFO (后进先出) 数据结构,你可以想象在一个 LIFO 数据结构中,最后添加到结构中的变量必须是首先被删除的。变量以其添加的顺序的 相反顺序 从栈中 移除


2
栈是LIFO,不是FIFO。(队列是FIFO。) - Spire

4

它们按照反向分配顺序被销毁,参见这个SO问题。在这种情况下,这意味着x2将在x1之前被销毁。


3

不错的链接。它提供了一个权威来源对许多破坏性订单相关问题的简短回答。 - Jakob Stark

2
它们将按照相反的顺序被摧毁,与它们建造的顺序相反。

实际上,按照它们构建的相反顺序。 - James Kanze

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接