在另一个作用域/函数中调用捕获的lambda函子时,实际发生了什么?

时间:2019-05-20 19:29:34

标签: c++ templates lambda c++14 functor

问题/问题的超简短说明

一个lambda表达式,它捕获变量,并作为函子传递给函数。我的困惑在于,lambda修改了它捕获的变量……但是,即使在完全不同的范围内,捕获的变量也是如此。

前言

这不是问题,但是更多地是关于内部和编译器代码的问题。就像标题和标签中一样,它与lambda,捕获,函子和模板有关。我本人是一个非常初级的程序员,英语不是我的母语,所以如果事情不太清楚,我会找借口。最好也很自由地使用汽车可能不在问题的“范围”内。而是lambda,函子和模板。我也搜索了互联网,但是要么搜索错误,要么这是对lambda和其他东西的混淆/混淆。

代码和问题的解释

  • 我有一个模板化函数riddle(),该函数具有两个参数/类型:functorsomething。在函数的主体中,有一个简单的for循环,循环从0到6,并将这些数字与functor一起传递给something
  • main()中创建了一个向量vec。稍后将很重要。
  • 函数riddle()被两个lambda调用。首先是一个通过引用捕获并获得两个auto变量的变量。它还返回一个auto,并且(!!!)将第一个auto变量推回到该vec
  • riddle()获得的第二个lambda是返回auto的lambda。
  • vec的内容显示从0到6的数字。

(问题的解释在代码后。)

最小的可复制示例

template <typename ftype, typename stype>
auto riddle(ftype functor, stype something) {
    for (int i = 0; i <= 6; i++) { 
        functor(i, something); 
    };
};
int main() {
    std::vector<int> vec;
    riddle(
        [&](auto o, auto p)->auto { vec.push_back(o); },    // functor
        []()->auto {return; }    // something
    );
    for (auto i : vec) { std::cout << "\n " << i; }; // prints numbers 0 to 6
    std::cin >> vec[0];    // just so it shows the results before a return
    return 0;
};

此代码可在C ++ 14及更高版本上运行,并且已在MS Visual Studio 2017和CodeBlocks 17.12中进行了测试,并且还在发行和调试配置中进行了测试。

第一个问题/问题

最后一个要点是使我感到困惑的部分。有人向我解释说,捕获的lambda只能获取在lambda调用范围内的变量。在这种情况下,lambda / functor在完全不同的作用域和函数中被调用,但仍会以某种方式修改它在写入位置捕获的向量。我尝试了一下,当更深层地传递另一个函数,作为指针甚至传递给另一个线程时,它仍然像这样工作。

问题是:实际上,编译器在这里做什么?是否创建一个(lambda?)对象,该对象包含对该向量的引用/指针?如果没有这样的lambda,这种事情会容易做到吗?这是残酷的低效,还是编译器以某种方式对其进行了优化?该lambda是否应该由编译器“转换”或“内联”,从而使其无法看到该向量?

第二个问题/问题

尽管这个问题不那么重要,但它是第二个lambda和something函数中的riddle()实际发生的情况。它是什么类型?它是空的吗? nullptr?一个功能/功能?

0 个答案:

没有答案