C++ 将唯一的_ptr移动到lambda中时,为什么不能调用reset?

C++ 将唯一的_ptr移动到lambda中时,为什么不能调用reset?,c++,c++11,lambda,unique-ptr,capture-list,C++,C++11,Lambda,Unique Ptr,Capture List,将std::unique_ptr移动到lambda中时,无法对其调用reset(),因为它似乎是常量: error C2662: void std::unique_ptr<int,std::default_delete<_Ty>>::reset(int *) noexcept': cannot convert 'this' pointer from 'const std::unique_ptr<int,std::default_delete<_Ty>&g

std::unique_ptr
移动到lambda中时,无法对其调用
reset()
,因为它似乎是常量:

error C2662: void std::unique_ptr<int,std::default_delete<_Ty>>::reset(int *) noexcept': cannot convert 'this' pointer from 'const std::unique_ptr<int,std::default_delete<_Ty>>' to 'std::unique_ptr<int,std::default_delete<_Ty>> &
错误C2662:void std::unique_ptr::reset(int*)noexcept::无法将“this”指针从“const std::unique_ptr”转换为“std::unique_ptr”&
#包括
int main()
{
自动u=std::unique_ptr();
自动l=[v=std::移动(u)]{
v、 reset();//这不会编译
};
}
  • 为什么会发生这种情况
  • 是否可以通过另一种方式捕获
    std::unique_ptr
    ,从而允许在lambda中调用
    reset()
    (使用C++17或更高版本)
  • 为什么会发生这种情况
  • 因为

    除非lambda表达式中使用了关键字
    mutable
    ,否则函数调用操作符是const限定的,并且通过copy捕获的对象在此
    操作符()中是不可修改的

  • 是否可以通过另一种方式捕获
    std::unique_ptr
    ,从而允许在lambda中调用
    reset()
  • 您需要将其标记为
    mutable

    可变:允许主体修改复制捕获的参数,并调用其非常量成员函数

    e、 g

  • 为什么会发生这种情况
  • 因为lambda在默认情况下是不可变的。因此,所有捕获的对象都是常量<代码>重置
    是一个修改唯一指针的非常量成员函数

  • 是否可以用另一种方式捕获std::unique_ptr,从而允许在lambda中调用reset()(使用C++17或更高版本)
  • 对。声明lambda可变:

    [captures](arguments) mutable { body }
                          ^^^^^^^
    
    这是可能的,因为C++11引入了lambda。可变lambda的所有捕获的非常量对象都是非常量副本。

    要对lambda的“成员”进行变异,需要
    可变
    关键字:

    auto l = [v = std::move(u)] () mutable {
        v.reset();
    };
    

    在lambda中,其数据成员在默认情况下是不可变的。您需要将
    mutable
    说明符附加到lambda表达式中

    或者,您可以通过引用捕获
    唯一的\u ptr
    ,例如:

    #include <memory>
    
    int main()
    {
        auto u = std::unique_ptr<int>();
        auto l = [&v = u]{
            v.reset(); 
        };
    }
    
    #包括
    int main()
    {
    自动u=std::unique_ptr();
    自动l=[&v=u]{
    v、 重置();
    };
    }
    
    很可能lambda将超过它声明的范围,因此引用捕获将dangle@Caleth这取决于上下文,但为什么呢?当lambda超出范围时,
    v
    不会自动重置吗?@L.F.是的,它会重置,并且它的析构函数与
    const
    ptr一起工作。但是,如果指针的生命周期需要在作用域结束之前结束(或者应该分配另一个指针,或者应该将托管对象的所有权转移到另一个唯一的\u ptr),则需要非常量唯一的\u ptr。
    auto l = [v = std::move(u)] () mutable {
        v.reset();
    };
    
    #include <memory>
    
    int main()
    {
        auto u = std::unique_ptr<int>();
        auto l = [&v = u]{
            v.reset(); 
        };
    }