You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++移动重载与析构函数调用逻辑理论正确性核验

结论

你的理解完全符合C++未开启返回值优化(RVO)场景下的标准对象生命周期逻辑,我们可以结合运行输出逐段验证:

执行流程对应验证

  1. main函数执行初始化:foo my{5}调用普通构造函数创建初始my对象,调用my.print()输出第一行01234
  2. 执行foo_test()调用:
    • 函数内构造局部对象in{10}
    • 返回in时触发移动构造,创建返回的临时foo对象,对应输出move cons was called,移动完成后原局部对象in的s被置0、p置空
    • 函数退出前局部对象in销毁,调用析构输出foo destructor0,和你的推导完全一致
  3. foo_test()返回的临时右值对象赋值给my,触发移动赋值重载,对应输出move = overload was called,移动完成后临时对象的s被置0、p置空
  4. 赋值语句执行结束,临时对象生命周期到期销毁,调用析构输出foo destructor0
  5. 执行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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 08:36:04