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

如何传递捕获unique_ptr的Lambda作为回调函数?

解决Lambda移动捕获unique_ptr后传递给回调的问题

我来帮你梳理下问题所在,以及怎么正确实现你的需求:

首先,你的代码里有两个常见问题:一是Lambda广义捕获的语法写错了,二是没注意到捕获了unique_ptr的Lambda是不可拷贝、只能移动的类型,传递时需要用移动语义。

核心原理

std::unique_ptr是独占所有权的智能指针,本身不支持拷贝操作。当你用广义捕获把它移动到Lambda内部后,这个Lambda就继承了unique_ptr的特性——只能被移动,不能被拷贝。而std::function<void(void)>虽然可以容纳这种Callable,但必须通过移动的方式传递,不能直接拷贝。

正确实现代码

下面是修正后的完整示例,你可以参考:

#include <memory>
#include <functional>
#include <cstdio>

// 按值接收回调的函数
void set_callback(std::function<void(void)> cb) {
    // 这里可以存储回调,或者直接调用
    cb();
}

// 按右值引用接收回调的函数
void move_callback(std::function<void(void)> &&cb) {
    // 转交给set_callback时也要用std::move,避免拷贝
    set_callback(std::move(cb));
}

void test() {
    auto a_ptr = std::make_unique<int>(10);
    
    // 正确的广义移动捕获:把a_ptr的所有权转移到Lambda内部
    auto lambda = [a_ptr = std::move(a_ptr)]() {
        if (a_ptr) {
            printf("捕获到的值:%d\n", *a_ptr);
        }
    };
    
    // 注意:必须用std::move传递lambda,因为它不可拷贝
    set_callback(std::move(lambda));
    
    // 直接传递临时Lambda更简洁,临时对象本身就是右值,无需std::move
    auto another_ptr = std::make_unique<int>(20);
    set_callback([a_ptr = std::move(another_ptr)]() {
        printf("临时Lambda捕获的值:%d\n", *a_ptr);
    });
    
    // 给接收右值引用的函数传递回调
    auto third_ptr = std::make_unique<int>(30);
    move_callback(std::move([a_ptr = std::move(third_ptr)]() {
        printf("右值回调捕获的值:%d\n", *a_ptr);
    }));
}

常见编译失败原因解析

  1. 语法错误:你写的[a_ptr = std::move(a_ptr...漏掉了闭合的),这是最基础的语法问题,编译器会直接报错。
  2. 尝试拷贝不可拷贝的Lambda:如果直接写set_callback(lambda);而不是set_callback(std::move(lambda));,编译器会提示无法拷贝Lambda——因为捕获了unique_ptr,Lambda的拷贝构造函数已被删除,只能通过移动转移所有权。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 07:39:13