【发布时间】:2020-06-28 05:45:27
【问题描述】:
在以下代码中(使用-std=c++14 -Wall -fno-elide-constructors 在 gcc 9.2 上构建):
struct Noisy {
Noisy() { std::cout << "Default construct [" << (void*)this << "]\n"; }
Noisy(const Noisy&) { std::cout << "Copy construct [" << (void*)this << "]\n"; }
Noisy(Noisy&&) { std::cout << "Move construct [" << (void*)this << "]\n"; }
Noisy& operator=(const Noisy&) { std::cout << "Copy assignment" << std::endl; return *this; }
Noisy& operator=(Noisy&&) { std::cout << "Move assignment" << std::endl; return *this; }
~Noisy() { std::cout << "Destructor [" << (void*)this << "]\n"; }
};
Noisy f() {
Noisy x;
return x;
}
Noisy g(Noisy y) {
return y;
}
int main(void) {
Noisy a;
std::cout << "--- f() ---\n";
Noisy b = f();
std::cout << "b [" << (void*)&b << "]\n";
std::cout << "--- g(a) ---\n";
Noisy c = g(a);
std::cout << "c [" << (void*)&c << "]\n";
std::cout << "---\n";
return 0;
}
产生这种结果的原因:
Default construct [0x7ffc4445737a]
--- f() ---
Default construct [0x7ffc4445735f]
Move construct [0x7ffc4445737c]
Destructor [0x7ffc4445735f]
Move construct [0x7ffc4445737b]
Destructor [0x7ffc4445737c]
b [0x7ffc4445737b]
--- g(a) ---
Copy construct [0x7ffc4445737e]
Move construct [0x7ffc4445737f]
Move construct [0x7ffc4445737d]
Destructor [0x7ffc4445737f]
Destructor [0x7ffc4445737e]
c [0x7ffc4445737d]
---
Destructor [0x7ffc4445737d]
Destructor [0x7ffc4445737b]
Destructor [0x7ffc4445737a]
为什么 f() 中的本地 Noisy 对象 [0x7ffc4445735f] 的副本在移动到 f 的返回地址后立即被破坏(并且在 b 的构造开始之前);而g() 似乎没有发生同样的情况?
IE。在后一种情况下(当g() 执行时),函数参数Noisy y、[0x7ffc4445737e] 的本地副本仅在c 准备好构造后被销毁。它不应该在被移动到g的返回地址后立即被销毁,就像f()一样吗?
【问题讨论】:
-
我编辑了代码,为每个变量使用不同的名称,这样可以避免在答案谈到每个变量时造成混淆