在C++中为临时库调用析构函数的顺序是什么
What is the order of calling destructors for temporaries in C++?
考虑以下代码:
#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();
}
使用GCC编译并运行会产生以下输出:
~C
~A
~B
当使用其他编译器编译时,是否保证类型A、B和C的临时对象的析构函数将按此顺序调用?一般来说,如果存在临时性,那么析构函数调用临时性的顺序是什么?
让我们来谈谈子表达式及其排序。如果E1
在E2
之前被排序,则意味着E1
必须在E2
之前被完全求值。如果E1
与E2
一起被unsequence,则意味著E1
和E2
可以按任何顺序求值。
对于f(A()) << B()
,在您的情况下与f(A()).operator<<(B())
相同,我们知道:
- CCD_ 11在CCD_
- CCD_ 13在CCD_
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中观察到的顺序。请注意,破坏的顺序总是与构造的顺序相反。
未指定表达式f(A()) << B();
的求值顺序。因此,建造/销毁的顺序也没有具体说明。
未指定<<
操作数的求值顺序。因此,秩序无法得到保证。只有短路运算符&&
、||
、三元运算符?:
和逗号,
运算符具有明确定义的操作数求值顺序。对于其他操作数,不必先计算左操作数,再计算右操作数(反之亦然)。
此外,不要将运算符优先级或关联性与求值顺序混淆。对于给定的表达式E1 op E2
,只需要在应用运算符op
之前,E1
和E2
都应该被求值,但在它们之间,E1
和E2
可以按任何顺序求值。
当表达式中有多个运算符(如E1 op1 E2 op2 E3
)时,优先级规则决定应用运算符的顺序。
当同一运算符被多次使用时,即在E1 op E2 op E3
中,是将其解释为(E1 op E2) op E3
还是E1 op (E2 op E3)
,关联性用于决定哪些操作数绑定到哪个运算符。
相关文章:
- 析构函数调用
- 在具有向量的类构造函数中进行析构函数调用
- 从 c++ 中派生类的析构函数调用虚函数
- C++析构函数调用两次,堆栈分配的复合对象
- C++ 在析构函数调用之前删除的动态成员数组
- 析构函数调用c++中的一个向量
- Singleton模式中的手动析构函数调用:调用多次
- 从内部类的析构函数调用虚拟函数
- 与 boost odeint 集成期间的析构函数调用
- 堆栈展开如何与析构函数调用有关?
- C++:优化析构函数调用
- 以逗号分隔的表达式中的析构函数调用
- GCC 9.1 返回 void& 作为显式析构函数调用的结果类型。这是一个错误吗?
- 从C++中的虚拟析构函数调用虚拟方法
- 从指针返回对象时出现意外的析构函数调用
- 使用 decltype 显式析构函数调用
- C++析构函数调用了错误的对象
- 了解虚拟函数和析构函数调用
- 多重继承析构函数调用他自己和父析构函数?c++
- 析构函数调用表单不适当的库