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

如何在Lambda中正确移动unique_ptr并存储到deque?

问题:将unique_ptr移动到Lambda后存入deque编译失败

尝试将unique_ptr资源移动到Lambda表达式中,并将其存储到deque容器中,示例代码如下:

#include <iostream>
#include <cstring>
#include <memory>
#include <thread>
#include <deque>

// base class
class MyBase
{
public:
    char* _data;
    int _len;
    
public:
    MyBase(int l)
        : _len(l)
    {
        _data = new char(_len); // 注意:此处应为new char[_len],否则只分配单个char
    }
    
    virtual ~MyBase()
    {
        delete[] _data;
    }
    
    MyBase(const MyBase& src)
        : _len(src._len)
    {
        _data = new char[_len];
        std::memcpy(_data, src._data, _len);
    }
    
    MyBase(MyBase&& src)
        : _len(std::move(src._len))
    {
        _data = src._data;
        src._data = nullptr;
    }
    
    MyBase& operator = (const MyBase& src)
    {
        if (&src == this)
            return *this;
    
        _len = src._len;
        if (_data != nullptr)
            delete[] _data;
        _data = new char[_len];
        std::memcpy(_data, src._data, _len);
    }
    
    MyBase& operator = (MyBase&& src)
    {
        if (&src == this)
            return *this;
        
        _len = std::move(src._len);
        _data = src._data;
        src._data = nullptr;
    }
};


class MyTest : public MyBase
{
    int _d;
    
public:
    MyTest(int d, int l)
        : MyBase(l)
        , _d(d)
    {
    }
    
    ~MyTest()
    {
    }
    
    MyTest(const MyTest& src)
        : MyBase(src)
        , _d(src._d)
    {
    }
    
    MyTest(MyTest&& src)
        : MyBase(std::move(src))
        , _d(std::move(src._d))
    {
    }
    
    MyTest& operator = (const MyTest& src)
    {
        if (&src == this)
            return *this;
    
        MyBase::operator = (src);
        _d = src._d;
        return *this;
    }
    
    MyTest& operator = (MyTest&& src)
    {
        if (&src == this)
        return *this;

        MyBase::operator = (std::move(src));
        _d = std::move(src._d);
        return *this;
    }
};

int main()
{
    std::unique_ptr<MyTest> m = std::make_unique<MyTest>(10, 5);
    
    // move resource
    std::thread t = std::thread([s = std::move(m)]()
    {
        std::cout << "start" << std::endl;
        
        std::deque<std::unique_ptr<MyTest>> container;
        container.push_back(std::move(s));

        std::this_thread::sleep_for(std::chrono::milliseconds(1000));
        std::cout << "finish" << std::endl;
    });

    t.join();

    return 0;
}

编译错误信息

In file included from /usr/include/x86_64-linux-gnu/c++/9/bits/c++allocator.h:33,
                 from /usr/include/c++/9/bits/allocator.h:46,
                 from /usr/include/c++/9/string:41,
                 from /usr/include/c++/9/bits/locale_classes.h:40,
                 from /usr/include/c++/9/bits/ios_base.h:41,
                 from /usr/include/c++/9/ios:42,
                 from /usr/include/c++/9/ostream:38,
                 from /usr/include/c++/9/iostream:39,
                 from main.cpp:9:
/usr/include/c++/9/ext/new_allocator.h: In instantiation of ‘void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = std::unique_ptr<MyTest>; _Args = {const std::unique_ptr<MyTest, std::default_delete<MyTest> >&}; _Tp = std::unique_ptr<MyTest>]’:
/usr/include/c++/9/bits/alloc_traits.h:483:4:   required from ‘static void std::allocator_traits<std::allocator<_CharT> >::construct(std::allocator_traits<std::allocator<_CharT> >::allocator_type&, _Up*, _Args&& ...) [with _Up = std::unique_ptr<MyTest>; _Args = {const std::unique_ptr<MyTest, std::default_delete<MyTest> >&}; _Tp = std::unique_ptr<MyTest>; std::allocator_traits<std::allocator<_CharT> >::allocator_type = std::allocator<std::unique_ptr<MyTest> >]’
/usr/include/c++/9/bits/stl_deque.h:1574:30:   required from ‘void std::deque<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = std::unique_ptr<MyTest>; _Alloc = std::allocator<std::unique_ptr<MyTest> >; std::deque<_Tp, _Alloc>::value_type = std::unique_ptr<MyTest>]’
<span class="error_line" onclick="ide.gotoLine('main.cpp',130)"></span>main.cpp:130:41:   required from here
/usr/include/c++/9/ext/new_allocator.h:146:4: error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = MyTest; _Dp = std::default_delete]’
  146 |  { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
      |    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/9/memory:80,
                 from main.cpp:11:
/usr/include/c++/9/bits/unique_ptr.h:414:7: note: declared here
  414 |       unique_ptr(const unique_ptr&) = delete;
      |       ^~~~~~~~~~

问题原因与修正方案

原因分析

默认情况下,Lambda表达式的operator()是const成员函数,这意味着Lambda内部捕获的变量s是const的。当执行std::move(s)时,得到的是const std::unique_ptr<MyTest>&&类型,而std::unique_ptr的拷贝构造函数已被显式删除,只能接受非const的右值进行移动构造,因此编译器报错。

修正方法

给Lambda添加mutable关键字,取消其operator()的const属性,这样捕获的s在Lambda内部可以被修改(移动操作会修改原对象的状态):

std::thread t = std::thread([s = std::move(m)]() mutable // 添加mutable
{
    std::cout << "start" << std::endl;
    
    std::deque<std::unique_ptr<MyTest>> container;
    container.push_back(std::move(s));

    std::this_thread::sleep_for(std::chrono::milliseconds(1000));
    std::cout << "finish" << std::endl;
});

额外提示

代码中MyBase构造函数里的_data = new char(_len);存在问题:此处使用圆括号()只会分配单个char并初始化为_len的值,而非长度为_len的char数组,应改为_data = new char[_len];,避免后续内存访问越界或析构时的未定义行为。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 20:01:02