C++析构函数和函数调用顺序

13

假设我有以下片段:

Foo foo;
....
return bar();

现在,C++标准是否保证bar()在foo::~Foo()之前被调用?还是由编译器/实现来决定?

谢谢!


你的C++教材对这个主题有什么说法? - anon
2
你所说的这本书是什么?它是否类似于 Stack Overflow,但经过编辑并放在纸上? - anon
5个回答

16

这是保证行为。实际执行的过程如下展开:

0: enter block (scope)
1: Foo::Foo()
2. evaluation of bar(); as expression in return statement
3. save result of the expression as value returned from function
4. finalize return statement to leave function to its caller (request exit from current scope)
5: exit block (scope) with call to  Foo::~Foo()

以下是一些来自标准的参考文献:

  • 通常程序执行保证

1.9 程序执行

10 每个带有自动存储期的对象实例(3.7.2)都与进入其块相关联。

  • foo 具有自动存储期,并且:

3.7.2 自动存储期

1 显示声明为自动或注册存储类,未显式声明为静态或外部链接的本地对象具有自动存储期。这些对象的存储持续到创建它们的块退出。

  • return 语句的实际效果是什么

6.6.3 return 语句

2 (...)表达式的值被返回给函数的调用者

6.6 跳转语句 (return 属于跳转语句)

2 在离开作用域时(不管如何),对于具有自动存储期的所有构造对象(3.7.2),将调用析构函数(12.4)。

  • 什么保证了该效果会发生

6.7 声明语句

2 在块中声明的具有自动存储期的变量在退出该块时被销毁。

12.4 析构函数

10 析构函数被隐式调用(1)对于具有静态存储期的构造对象(3.7.1)在程序终止(3.6.3)时,(2)对于具有自动存储期的构造对象(3.7.2)当创建对象的块退出(6.7)时。

从 C++ 标准的所有细节中抓住单个想法并不容易。希望快速概述将帮助您自己进行这种分析。


7

是的,在foo对象的析构函数被调用之前,bar()函数将被调用。

标准规定:

6.6:“无论如何脱离作用域,都会为该作用域中声明的所有具有自动存储期(3.7.2)(命名对象或临时对象)的构造对象调用析构函数(12.4),按照它们的声明顺序的反向顺序。”

直到return语句执行完毕,才离开作用域。


5
调用bar()的结果必须在包含Foo的堆栈帧被清理之前进行评估,因此是的,在Foo::~Foo()之前将调用bar()。

3

当离开作用域时,对象会被销毁。

return 离开作用域,但在执行 bar() 之前无法返回。因此,bar() 被调用。


2

想象一下,如果它是 return bar(foo);?这只是必须工作的,如果销毁顺序取决于是否将其作为参数传递,那将是愚蠢的。


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