在C++中为临时对象调用析构函数的顺序是什么?

vit*_*aut 5 c++ destructor temporary object-lifetime

请考虑以下代码:

#include <iostream>

struct A {
  ~A() { std::cout << "~A" << std::endl; }
};

struct B {
  ~B() { std::cout << "~B" << std::endl; }
};

struct C {
  ~C() { std::cout << "~C" << std::endl; }

  void operator<<(const B &) {}
};

C f(const A &a = A()) {
  return C();
}

int main() {
  f(A()) << B();
}
Run Code Online (Sandbox Code Playgroud)

使用GCC进行编译并运行会提供以下输出:

~C
~A
~B
Run Code Online (Sandbox Code Playgroud)

是否保证在与其他编译器一起编译时,将按此顺序调用类型A,B和C的临时对象的析构函数?一般来说,如果有的话,析构函数调用的顺序是什么?

Xeo*_*Xeo 10

我们来谈谈子表达式及其排序.如果E1之前测序 E2,这意味着E1必须充分评估之前E2就是.如果E1未测序用 E2,该装置E1E2可以以任何顺序进行评估.

因为f(A()) << B(),在你的情况下f(A()).operator<<(B()),我们知道:

  • A()在之前排序f(...),
  • f(...)operator<<和之前排序
  • B() 以前是排序的 operator<<

这也告诉我们:

  • A() 以前是排序的 operator<<
  • A() 没有顺序 B()
  • f(...) 没有顺序 B()

如果我们假设RVO,为了不使事情复杂化,编译器可以评估子表达式的可能顺序是:

  • A()- > f(...)- > B(),屈服~B()- > ~C()- >~A()
  • A()- > B()- > f(...),屈服~C()- > ~B()- >~A()
  • B()- > A()- > f(...),屈服~C()- > ~A()- >~B()

后者是在OP中观察到的顺序.请注意,破坏的顺序始终与构造的顺序相反.