You need to enable JavaScript to run this app. C++闭包底层行为测试中两次移动构造调用的原因问询
优惠活动
大模型
产品
解决方案
定价
更多

C++闭包底层行为测试中两次移动构造调用的原因问询

C++闭包移动构造触发逻辑说明

测试代码

#include <iostream>
#include <iomanip>
#include <functional>
#include <list>

using namespace std;

class A
{
    list<int> ints = { 1, 2 };
    void display(string msg) const {
        cout << setw(8) << msg << ": this = 0x" << this << ", ints.front() = " << ints.front() << endl;
    }
public:
    A() { ints.front() += 1; display("A()"); }
    A(const A& other) : ints(other.ints) { ints.front() += 1; display("A(A&)"); }
    A(const A&& other) noexcept : ints(other.ints) { ints.front() += 1; display("A(A&&)"); }
    ~A() { display("~A()"); }
    void doSomething() const { display("A doing something"); }
};


function<void (void)> fn()
{
    A a;

    auto rfn = [=]() { 
        cout << "In Lambda: &a = 0x" << &a << endl;
        a.doSomething(); 
    };

    return rfn;
}

int main()
{
    {
        auto fn2 = fn();
        fn2();
    }
    return 0;
}

运行输出(VS2019无优化环境)

A(): this = 0x010FF948, ints.front() = 2
   A(A&): this = 0x010FF934, ints.front() = 3
  A(A&&): this = 0x010FF838, ints.front() = 4
  A(A&&): this = 0x010FFA4C, ints.front() = 5
    ~A(): this = 0x010FF838, ints.front() = 4
    ~A(): this = 0x010FF934, ints.front() = 3
    ~A(): this = 0x010FF948, ints.front() = 2
In Lambda: &a = 0x010FFA4C
A doing something: this = 0x010FFA4C, ints.front() = 5
    ~A(): this = 0x010FFA4C, ints.front() = 5

两次移动构造的触发原因

以下分析基于*Visual Studio 2019默认无优化(/Od)*的std::function实现,开启O2优化后编译器会触发复制消除省略这两次移动操作:

  • 第一次移动构造:fn()的返回值类型为std::function<void(void)>,而代码中定义的rfn是匿名lambda类型,需要先做类型转换:局部lambda对象是return语句中的右值,移动构造为临时std::function对象时,lambda内部存储的A成员会被移动到std::function的内部存储中,对应地址0x010FF838的A(A&&)输出。
  • 第二次移动构造:fn()返回的临时std::function对象属于右值,在main函数中构造fn2变量时,会调用std::function的移动构造函数,将其内部存储的A成员移动到fn2的内部存储中,对应地址0x010FFA4C的A(A&&)输出。

两次移动完成后,中间临时存储的A对象(lambda内的A、第一次构造的std::function内的A)会依次析构,最终fn2中存储的A对象会在作用域结束后析构。

内容的提问来源于stack exchange,提问作者melston

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.12 16:33:04