什么时候是临时调用的析构函数

时间:2015-03-31 18:23:30

标签: c++ c++11

我想知道何时为C ++ 03和C ++ 11调用temporay的析构函数

假设我有以下案例

foo method()
{
   foo f;
   ......
   ......
   return foo;
}

void doSomething()
{
   foo f = method();
   ....
}

假设我正在使用标志-fno-elide-constructors,因为我希望在理论上理解何时调用临时函数的析构函数。 因此,C++03完成method()时,foo中的上述代码使用其复制构造函数创建foo f = method()的副本。之后在语句foo处再次调用method的复制构造函数。 在这种情况下对于C ++ 03何时是这个tempo的析构函数(由doSomething()传递)被调用?是否在method范围的末尾调用 现在我想将相同的案例应用于涉及移动语义的C ++ 11。对于C ++ 11,当foo返回foo f = method()的副本时。然后当调用method()时,调用foo的移动构造函数。 所以在C ++ 11的情况下,何时从{{1}}返回的临时对象的析构函数被调用?

2 个答案:

答案 0 :(得分:6)

  

我想知道什么时候要求两个时间的析构函数   C ++ 03和C ++ 11

在表达式的末尾调用R-Value(临时)的析构函数。

提供您的代码:

foo method()
{
   foo f;
   ......
   ......
   return foo;
}

void doSomething()
{
   foo f = method();
   ....
}

method()创建一个对象。当该对象超出范围时(在方法结束时),将调用析构函数(如果没有优化)。

调用“foo f =”...导致调用foo的复制构造函数。之后表达式结束,导致返回的对象(临时)被破坏。当对象“f”的析构函数在doSomething结束时超出范围时被调用。

答案 1 :(得分:5)

C ++ 03

  

当一个实现引入一个具有非平凡构造函数(12.1)的类的临时对象时,它就是   应确保为临时对象调用构造函数。同样,应该要求析构函数   一个临时的非平凡析构函数(12.4)。 临时对象被作为评估全表达式(1.9)的最后一步而被销毁,该表达式(词法上)包含创建它们的点。这甚至是真的   如果评估以抛出异常结束。

(12.2 / 3;强调我的)

  

有两种情况下,临时人员在不同时刻被摧毁,而不是在完全结束时   表达。第一个上下文是表达式作为定义的声明符的初始值设定项   宾语。在该上下文中,保存表达式结果的临时值将持续到对象的为止   初始化完成。该对象是从临时副本初始化的;在这次复制过程中,   实现可以多次调用复制构造函数;一旦临时被摧毁   在初始化完成之前或之后复制。如果通过评估创建了许多临时工   在初始化器中,临时工作者以完成建造的相反顺序被摧毁。

(12.2 / 4;强调我的)

因此method()的临时结果在初始化结束时被销毁。

C ++ 11

  

当一个实现引入一个具有非平凡构造函数的类的临时对象时(12.1,   12.8),它应确保为临时对象调用构造函数。同样,析构函数应该是   用非平凡的析构函数(12.4)调用临时函数。 临时对象作为最后一步被销毁   在评估全表达式(1.9)时(词法上)包含创建它们的点。即使该评估以抛出异常结束,也是如此。破坏的价值计算和副作用   临时对象仅与完整表达式相关联,而不与任何特定子表达式相关联。

(12.2 / 3;强调我的)

C ++ 11没有明确说明用作初始化程序的临时文件在初始化完成之前一直存在。相反,在1.9 / 10中有一个例子:

  

[示例:

struct S {
  S(int i): I(i) { }
  int& v() { return I; }
private:
  int I;
};

S s1(1); // full-expression is call of S::S(int)
S s2 = 2; // full-expression is call of S::S(int)

void f() {
  if (S(3).v()) // full-expression includes lvalue-to-rvalue and
                // int to bool conversions, performed before
                // temporary is deleted at end of full-expression    
  { }
}
     

- 结束示例]

这可能是为了澄清当初始化具有非平凡初始化的对象时,有一个包含对其构造函数的调用的完整表达式。这样就无需明确说明C ++ 03中12.2 / 4中所述的内容。