c++:为什么一个特定的参数必须由lambda中的值捕获
c++: why a specific parameter must be captured by value in lambda
#include <iostream>
#include <functional>
#include <utility>
using namespace std;
typedef std::function<void(const string&, const string&, const bool, const bool)>
Callback_T;
class A {
public:
void
process(const string &a, const string &b, const bool c, const bool d, const int e)
{
cout << "a: " << a << " b: " << b << " c: " << c << " d: " << d << " e: " << e << endl;
}
Callback_T
constructCallback(const int &e)
{
Callback_T callback =
[&, this, e](auto&&...args) // <--- here, e must be captured by value, why?
{
this->process(
std::forward<decltype(args)>(args)...,
e);
};
return callback;
}
};
int main()
{
A a;
auto cb = a.constructCallback(20);
cb("A", "B", true, false);
}
上述程序输出:"a:Ab:Bc:1 d:0 e:20"但如果我把捕获e的行改为:
[&,this,&e]
它输出:"a:Ab:Bc:1 d:0 e:263440408",似乎表明e未定义/初始化。
为什么只通过有价值的作品来捕捉它?
您所拥有的是一个悬空引用。由于e
是一个参考参数,它与其他参数绑定。在这种情况下,它是根据文字20
创建的临时对象。当函数结束,留下callback
并引用一个不再存在的对象时,这个临时性就超出了作用域。
当您通过值捕获时,您否定了这个问题,因为lambda将存储它自己的e
副本,以确保它在constructCallback
返回后仍然有效。
通过引用捕获时,必须确保没有任何路径会留下对不存在的东西的引用。
因为调用函数时e
超出了作用域,并且您有一个悬空引用。在以下行中:
A a;
auto cb = a.constructCallback(20);
cb("A", "B", true, false);
调用constructCallback(20)
时,会创建一个值为20的本地e
,该值通过引用lambda捕获,然后在函数退出时销毁。因此,使用此引用是未定义的行为,并导致您观察到的垃圾值。如果改为按值捕获e
,则它将被复制,并且与lambda一样长。如果您确实需要通过引用使用e
,则需要确保在计算lambda之前它不会被破坏。
相关文章:
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 如何将lambda作为模板类的成员函数参数
- 使用自动推导的 lambda 参数作为常量表达式
- 如果模板没有可变参数,则 Lambda 被推导出为 std::function
- 将有状态的 lambda 传递到 C 样式函数中,而无需上下文参数
- 引用捕获和在 lambda 中通过引用发送参数有什么区别 (C++)
- 将__device__ lambda 作为参数传递给 __global__ 函数
- 将 lambda 函数作为参数传递C++
- 如何将 lambda 函数作为参数发送到另一个函数
- Lambda可以用作非类型模板参数吗
- 将参数传递给泛型 lambda 时复制构造函数不正确
- 如何确定捕获不可复制参数的 lambda 的类型?
- 省略C++可变参数 lambda 中的"auto"关键字?
- 如何访问可变参数 lambda 函数参数
- 可变参数 lambda 捕获的解决方法
- 传递给多个参数 lambda 表达式的参数
- 如何编写丢弃其参数的通用可变参数 lambda
- 使用c++参数lambda函数
- 将函数模板"pass"为泛型可变参数 lambda 返回语句是好方法吗?
- c++模板非类型参数lambda函数