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

时间:2010-02-03 23:32:46

标签: c++ destructor

假设我有以下snipplet:

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

现在,C ++标准是否保证在foo :: ~Foo()之前调用bar()?或者这是编译器/实现的选择吗?

谢谢!

5 个答案:

答案 0 :(得分:15)

保证行为。实际执行按如下方式展开:

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显式声明自动或注册或未显式声明的本地对象   static或extern具有自动存储持续时间。存储   这些对象会持续到创建它们的块为止。

  • return statement
  • 的实际效果是什么?
  

6.6.3退货声明

     

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

  

6.6跳转语句(返回属于跳转语句)

     

2退出范围(无论多么完成)时,将为所有人调用析构函数(12.4)   具有自动存储持续时间的构造对象(3.7.2)

  • 保证效果发生的原因
  

6.7声明声明

     

2块中声明的具有自动存储持续时间的变量是   从街区退出时被摧毁

  

12.4析构函数

     

对于构造的,隐式调用10个析构函数(1)   静态存储持续时间的对象   (3.7.1)程序终止时   (3.6.3),(2)对于构造对象   具有自动存储持续时间   (3.7.2)当其中的块   对象创建出口(6.7)

要掌握分散在所有C ++标准中的单一构思表单细节并不容易。希望快速概述也可以帮助您自己进行此类分析。

答案 1 :(得分:7)

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

标准说: 6.6:“退出范围(无论多么完成),析构函数(12.4)是 调用具有自动存储持续时间的所有构造对象 (3.7.2)在该范围内声明的(命名对象或临时对象), 按照他们声明的相反顺序。“

在返回语句完成之前,不会留下范围。

答案 2 :(得分:5)

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

答案 3 :(得分:3)

对象在离开范围时会破坏。

return离开范围,但在执行bar()之前无法返回。 Ergo,bar()被称为。

答案 4 :(得分:2)

试想一下,如果是return bar(foo);怎么办?只是才能工作,如果销毁顺序不同,那将是愚蠢的,这取决于你是否将其作为参数传递。