首页 > 解决方案 > c ++:为什么必须通过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:A b:B c:1 d:0 e:20”但是如果我将捕获e的那一行更改为:

[&,这个,&e]

它输出:“a:A b:B c:1 d:0 e:26340408 ”,似乎表明e未定义/初始化。

为什么只通过价值作品来捕捉它?

标签: c++c++11lambdac++14

解决方案


你所拥有的是一个悬空的参考。由于e是参考参数,因此它绑定到其他东西。在这种情况下,它是从文字创建的临时对象20。当函数结束callback并引用不再存在的对象时,此临时值超出范围。

当您按值捕获时,您会否定这个问题,因为 lambda 将存储它自己的副本,以e确保它在constructCallback返回后仍然有效。


通过引用捕获时,您必须确保没有路径会留下对不存在的东西的引用。


推荐阅读