将unique_ptr移至lambda时,为什么无法调用reset?

Roi*_*ton 34 c++ lambda unique-ptr c++11 capture-list

当移动std::unique_ptr到拉姆达,这是不可能的调用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>> &
Run Code Online (Sandbox Code Playgroud)
#include <memory>
int main()
{
    auto u = std::unique_ptr<int>();
    auto l = [v = std::move(u)]{
        v.reset(); // this doesn't compile
    };
}
Run Code Online (Sandbox Code Playgroud)
  1. 为什么会这样?
  2. 是否可以通过std::unique_ptr允许reset()在lambda(使用C ++ 17或更高版本)中调用的另一种方式捕获?

son*_*yao 51

  1. 为什么会这样?

因为lambda的函数调用运算符,

除非mutable在lambda-expression中使用了关键字,否则函数调用运算符是const限定的,并且通过copy捕获的对象在this内部不可修改operator()

  1. 是否有可能以std::unique_ptr允许reset()在lambda内调用的另一种方式捕获

您需要标记它mutable

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

例如

auto l = [v = std::move(u)]() mutable {
    v.reset();
};
Run Code Online (Sandbox Code Playgroud)


eer*_*ika 14

  1. 为什么会这样?

因为默认情况下,lambda是不可更改的。因此,所有捕获的对象都是const。reset是修改唯一指针的非常量成员函数。

  1. 是否有可能以另一种方式捕获std :: unique_ptr,从而允许在lambda中调用reset()(使用C ++ 17或更高版本)?

是。声明可变的lambda:

[captures](arguments) mutable { body }
                      ^^^^^^^
Run Code Online (Sandbox Code Playgroud)

从引入lambda的C ++ 11开始,这是可能的。可变lambda的所有捕获的非常量对象都是非常量副本。


Jar*_*d42 8

要变异Lambda的“成员”,您需要使用mutable关键字:

auto l = [v = std::move(u)] () mutable {
    v.reset();
};
Run Code Online (Sandbox Code Playgroud)


Vla*_*cow 5

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

另外,您也可以unique_ptr按引用捕获,例如:

#include <memory>

int main()
{
    auto u = std::unique_ptr<int>();
    auto l = [&v = u]{
        v.reset(); 
    };
}
Run Code Online (Sandbox Code Playgroud)

  • Lambda可能会超出其声明范围的范围,因此引用捕获将变得悬而未决 (2认同)