c++ - 如何将局部引用变量传递给 lambda 函数,但该函数将在其关闭已经完成时被调用?

标签 c++

下面的代码应该打印两个相同的整数,但事实并非如此。 JavaScript 中的类似程序会打印两个相同的数字。

在C++中似乎是合理的,因为当stdfun执行时,regfun已经完成,local_var 不存在那时不再

所以我的问题是,我们如何才能像 JavaScript 默认情况下那样,在其上下文的生命周期之外正确访问捕获的局部变量?

#include <functional>
#include <future>
#include <cmath>
#include <iostream>
#include <ctime>
#include <windows.h>
using namespace std;

int start_stdfun_in_a_new_thread(std::function<void()> stdfun)
{   
    int id = rand();
    std::function<void()> call = [=]()
    {
        Sleep(1000);//let regfun finish 
        stdfun();
    };
    std::async(std::launch::async,call);
    return id;
}

void regfun()
{
    int local_var = -1;
    std::function<void()> stdfun = [=,&local_var]() mutable -> void
    {
        cout<<local_var<<endl;
    };
    local_var = start_stdfun_in_a_new_thread(stdfun);
    cout<<local_var<<endl;
}

int main() 
{
    regfun();
    Sleep(1000000);
}

很难描述我的问题到底是什么,但我只需要像我们在 javascript 中所做的那样用 c++ 编写的东西。如果您非常熟悉 javascript,也许您可​​以完全理解我的意思。

最佳答案

您的 local_var 绑定(bind)到 local context,即当 regfun 退出时它就死了,这几乎是立即发生的。但是您的 lambda 通过引用捕获它,这意味着稍后执行 stdfun 时这是一个悬挂引用,因为到那时 local_var 已经死了。

所以这是未定义的行为。您需要的(JavaScript 所做的)是延长捕获变量的生命周期。但 C++11 lambda 不是这种情况,如 http://en.cppreference.com/w/cpp/language/lambda 中所述。 :

Dangling references

If an entity is captured by reference, implicitly or explicitly, and the function call operator of the closure object is invoked after the entity's lifetime has ended, undefined behavior occurs. The C++ closures do not extend the lifetimes of the captured references.

我看到两个解决方案:

  1. 一个解决方案是对您要捕获的对象进行堆分配,使用std::shared_ptr 指向它,然后捕获该指针按值(这会将其复制到 lambda 实例中)。最后一个共享指针实例将为您删除堆分配的对象。

  2. 如果可能,您还可以在某些其他上下文中在本地定义它,在任何情况下都超出其使用期限。 (在你的简单代码中是 main,但在大多数情况下你想要等待线程;启动和等待线程的上下文很可能是正确的上下文。)然后通过引用将其传递给 regfun,并通过引用捕获它。因此,即使 regfun 退出,它仍然是一个有效的引用(如果它在一个过时的上下文中)。

关于c++ - 如何将局部引用变量传递给 lambda 函数,但该函数将在其关闭已经完成时被调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20928732/

相关文章:

c++ - 临时对象的 Clang 6 中的模板参数推导被破坏

c++ - 如何从另一个源文件调用 main.cpp 中的静态函数?

c++ - CMAKE LINKING ERROR 与用户定义的共享库

c++ - 在构造函数中调用方法

c++ - 如何摆脱容器中的 weak_ptr

c++ - __func__ 和 __PRETTY_FUNCTION__ 之间的东西?

c++ - IplImages 中的 cv::putText

c++ - 忽略具有单个全局变量的 cpp 文件

c++ - 虚幻4中纹理的平均颜色

c++ - 将指针分配给 vector 的差异