C++移动重载与析构函数调用逻辑理论正确性核验
结论
你的理解完全符合C++未开启返回值优化(RVO)场景下的标准对象生命周期逻辑,我们可以结合运行输出逐段验证:
执行流程对应验证
main函数执行初始化:foo my{5}调用普通构造函数创建初始my对象,调用my.print()输出第一行01234- 执行
foo_test()调用:- 函数内构造局部对象
in{10} - 返回
in时触发移动构造,创建返回的临时foo对象,对应输出move cons was called,移动完成后原局部对象in的s被置0、p置空 - 函数退出前局部对象
in销毁,调用析构输出foo destructor0,和你的推导完全一致
- 函数内构造局部对象
foo_test()返回的临时右值对象赋值给my,触发移动赋值重载,对应输出move = overload was called,移动完成后临时对象的s被置0、p置空- 赋值语句执行结束,临时对象生命周期到期销毁,调用析构输出
foo destructor0 - 执行
my.print()输出0123456789,main函数执行结束my出作用域,调用析构输出foo destructor10
补充说明
如果开启O2及以上优化,编译器会触发返回值优化(RVO),直接把foo_test内部的in对象构造在my的内存地址上,会省略一次移动构造、两次析构的调用,不过这属于编译器优化范畴,你当前默认编译下的推导是完全正确的。
格式化代码与运行结果
Main.cpp
#include <iostream> class foo { int* p; int s; public: foo(int in) :s{ in }, p{ new int[in] }{ for (int i = 0; i < s; ++i) p[i] = i; } foo(foo&& a) :s{ a.s }, p{ a.p } {a.s = 0; a.p = nullptr; std::cout << "move cons was called" << std::endl; } foo& operator=(foo&& a) { delete[] p; p = a.p; s = a.s; a.s = 0; a.p = nullptr; std::cout << "move = overload was called"; return *this; } void print() { for (int i = 0; i < s; ++i) std::cout << p[i]; } ~foo() { std::cout << std::endl << "foo destructor" << s << std::endl; } }; foo foo_test() { foo in{10}; return in; } int main() { foo my{ 5 }; my.print(); std::cout << std::endl; my = foo_test(); my.print(); }
运行输出
01234 move cons was called foo destructor0 move = overload was called foo destructor0 0123456789 foo destructor10
内容的提问来源于stack exchange,提问作者HarryTra
相关产品推荐
相关产品推荐

