在带有可变模板功能的labmda中传递文字的正确参考时出现段错误

问题描述

代码如下

#include <functional>
#include <iostream>

using namespace std;
int foo(int a){
    cout<<a;
    return a;
}

template<typename R,typename ...Args>
function<void()> wrapper( R f,Args&& ... args) {
    function<void()> fun([&] { f(forward<Args...>(args...)); });//crash
    //function<void()> fun=bind(f,forward<Args...>(args...));
    return fun;
}

int main(){
    auto d=wrapper(foo,1);
    d();
    return 0;
}

当我使用bind时,一切都很好。但是当我使用lambda时,程序崩溃了。 我想知道是否有一种方法可以通过引用捕获lambda,但可以通过值捕获文字(以提高效率)?还是应该坚持使用bind?

解决方法

function<void()> fun([&] { f(forward<Args...>(args...)); });//crash

所有这些捕获的对象f和所有args都是通过引用捕获的。

所有参数都是wrapper的参数。

但是wrapper返回时,wrapper的所有参数都超出范围并被销毁。然后,您的lambda捕获的引用(全部都变成了悬空引用)。

wrapper的参数 可以 本身被引用时,我可能会在这里看到一些摆动的地方,而lambda然后捕获对原始对象,而不是wrapper参数本身。

但是,没有什么可以保证的。

因此,这几乎保证了未定义的行为。

确实有语法可以按值捕获f,而其他一切都可以通过引用来捕获,但这对您没有帮助。

auto d=wrapper(foo,1);

因为即使在这种情况下(即您正在使用的参数),您的参数也是一个prvalue,当wrapper返回时,它会冒烟,将lambda留着一个空袋子,悬空参考。

除了按值捕获 一切 之外,这里没有其他现实的选择。