将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>> &
#include <memory>
int main()
{
auto u = std::unique_ptr<int>();
auto l = [v = std::move(u)]{
v.reset(); // this doesn't compile
};
}
std::unique_ptr
的方式来允许在lambda(使用C ++ 17或更高版本)中调用reset()
?答案 0 :(得分:50)
- 为什么会这样?
因为lambda的函数调用运算符,
除非在lambda表达式中使用了关键字
mutable
,否则函数调用运算符是const限定的,并且复制的捕获对象在此operator()
内部是不可修改的。
和
- 是否可以通过另一种方式捕获
std::unique_ptr
,从而允许在lambda中调用reset()
您需要将其标记为mutable
。
可变:允许主体修改通过复制捕获的参数,并调用其非常量成员函数
例如
auto l = [v = std::move(u)]() mutable {
v.reset();
};
答案 1 :(得分:14)
- 为什么会这样?
因为默认情况下lambda是不可更改的。因此,所有捕获的对象都是const。 reset
是一个非常量成员函数,可修改唯一指针。
- 是否有可能以另一种方式捕获std :: unique_ptr,从而允许在lambda(使用C ++ 17或更高版本)中调用reset()?
是的。声明可变的lambda:
[captures](arguments) mutable { body }
^^^^^^^
这是可能的,因为C ++ 11中引入了lambda。捕获的可变lambda的所有非常量对象都是非常量副本。
答案 2 :(得分:8)
要变异Lambda的“成员”,您需要使用mutable
关键字:
auto l = [v = std::move(u)] () mutable {
v.reset();
};
答案 3 :(得分:5)
在lambda中,其数据成员默认情况下是不可变的。您需要将mutable
说明符附加到lambda表达式。
作为替代方案,您可以通过引用捕获unique_ptr
,例如:
#include <memory>
int main()
{
auto u = std::unique_ptr<int>();
auto l = [&v = u]{
v.reset();
};
}