我想使用结构化绑定声明将结构体的成员引入作用域。我希望优化器能够删除我实际上没有使用的变量,但这不是我的主要问题。我被一个意料之外的析构函数调用所困扰:
运行上述程序会产生以下结果:
#include <iostream>
using namespace std;
struct S {
int x = 0;
S() { cout << "S: " << this << endl; }
~S() { cout << "~S: " << this << endl; }
};
// Why does f() call ~S()?
void f(S const& s) {
auto [x] {s};
cout << "f: " << x << endl;
}
void g(S const& s) {
auto& [x] {s};
cout << "g: " << x << endl;
}
void h(S const& s) {
auto x = s.x;
cout << "h: " << x << endl;
}
int main(int, char**) {
S s;
f(s);
g(s);
h(s);
}
运行上述程序会产生以下结果:
S: 0x7fff32c81778
f: 0
~S: 0x7fff32c81740
g: 0
h: 0
~S: 0x7fff32c81778
https://godbolt.org/z/cjeTnvx8G
main()
函数末尾的析构函数调用是可以预料的。但为什么f()
会调用 ~S()
呢?
我已经阅读了cppreference上的文档,但显然我对C++的内部运作理解不够,无法发现这会导致析构函数的调用。
x
是自动存储中的S
。你是否期望它绑定为const S&
? - Brian61354270this
输出到构造函数和析构函数中有助于您了解创建和销毁的对象是什么,并且不仅仅打印出〜S
或f:
。如果您在析构函数中看到一个神秘地出现而没有对应构造函数中的this
,那么就知道您没有跟踪所有被调用的构造函数。 - PaulMcKenziex
是一个int
。请注意,operator<<
未为S
定义,因此如果x
是S
,程序将无法编译。 - jonas-schulze0x7fff32c81740
-- 你会发现你没有追踪正在被销毁的对象的构造函数。像S
的复制构造函数和移动构造函数之类的东西都没有在你的代码中输出。 - PaulMcKenzie