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

为何std::function在此处尝试调用已删除的拷贝构造函数?

为何std::function在此处尝试调用拷贝构造函数?
#include <functional>
struct MyFoo
{
    MyFoo() {}
    MyFoo(const MyFoo&) = delete;
    MyFoo(MyFoo&&) = default;
    MyFoo& operator=(const MyFoo&) = delete;
    MyFoo& operator=(MyFoo&&) = default;
    void operator()(int) {

    }
};

int main(void)
{
    std::function<void(int)> foo{MyFoo()};
}

错误信息:Error C2280 'MyFoo::MyFoo(const MyFoo &)': attempting to reference a deleted function

问题分析

你提到MyFoo是右值,按道理std::function应该移动而非拷贝它,但实际触发拷贝构造函数调用的核心原因是:C11至C17标准中,std::function的构造逻辑要求传入的可调用对象必须支持拷贝构造。

早期标准的std::function内部是通过存储对象拷贝的方式实现的,即便传入的是右值,其底层实现依然会尝试调用拷贝构造函数完成内部存储的初始化,这就导致被删除的拷贝构造函数被引用,触发编译错误。

解决方法

这个问题在C++20标准中已经被修复:std::function新增了支持仅可移动类型的构造重载,会通过std::move语义转移对象所有权。你可以通过两种方式解决:

  • 升级编译器到支持C++20的版本,原代码无需修改即可正常编译,std::function会自动移动MyFoo对象。
  • 若无法升级标准,可以用std::unique_ptr或std::shared_ptr包装MyFoo,间接绕开拷贝要求:
#include <functional>
#include <memory>

struct MyFoo
{
    MyFoo() {}
    MyFoo(const MyFoo&) = delete;
    MyFoo(MyFoo&&) = default;
    MyFoo& operator=(const MyFoo&) = delete;
    MyFoo& operator=(MyFoo&&) = default;
    void operator()(int) {

    }
};

int main(void)
{
    std::function<void(int)> foo{[ptr = std::make_unique<MyFoo>()](int x) {
        (*ptr)(x);
    }};
}

这里std::function存储的是可拷贝的lambda,lambda通过智能指针持有仅可移动的MyFoo对象,间接完成函数调用,规避了拷贝构造的限制。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 17:41:09