【问题标题】:C++ Lambda capture messing up local variable valueC ++ Lambda捕获弄乱局部变量值
【发布时间】:2016-04-15 07:49:30
【问题描述】:

我不确定这是 VS 2010 的问题还是我完全误解了某些东西。我正在通过需要修改局部变量的 lambda 函数创建一个 boost 线程:

    auto oCurrTime( boost::posix_time::microsec_clock::universal_time() );
    auto spRequestSequenceThread = make_unique<boost::thread>( [&oCurrTime, this]()
    {
        while ( !checkAgainstSpecificTime(oCurrTime) )
        {
            ...
        }
        :
        :
    }

在创建线程之前,oCurrTime 类似于 2864273654234872634,但在线程内该值会丢失,并且 oCurrTime 立即类似于 487465847564875465,从而使 while 循环(其中计算与某个特定时间的时间差)无用。

非常感谢您的帮助。

P.S.:以上代码是类函数的一部分

【问题讨论】:

  • 你的主线程在启动这个 lambda 线程后做了什么?你确定oCurrTime 不会消失,和/或被主线程同时访问吗?
  • 并发使用绝对不是这样。但我认为你对存在的事情是正确的,因为函数可能在线程结束之前返回。我没有考虑这一点,将立即检查...

标签: c++ variables lambda local capture


【解决方案1】:

看起来您从类方法执行线程 - 您在 lambda 捕获列表中提供 this。这也意味着oCurrTime 是局部变量,所以如果你通过引用捕获它:你使用&amp;,那么当你的线程执行时,oCurrTime 将从堆栈中删除,因为它定义时的作用域已经结束。

解决方案是在可能的情况下通过值传递oCurrTime(删除&amp;),或者在方法结束之前加入您的线程 - 如果可能的话。您也可以将oCurrTime 设为类变量。

【讨论】:

  • 是的,正如上面的答案,我想这是一个超出范围的问题。我会尝试使其成为成员变量...
  • @gilgamash 您可以按价值捕获
  • 是的,我可以这样做,但是线程内的值会发生变化(我没有通过上面的代码明确说明),因此对于这种特定情况,这不是一个选项。
  • @gilgamash 如果将 lambda 声明为 mutable,则可以修改捕获的值。
  • 好吧,我忘了。或者说得更好:我尽量避免可变。
【解决方案2】:

当您通过引用[&amp;oCurrTime] 捕获它时
如果oCurrTime 超出范围,您将拥有dangling reference

一种解决方案可能是按价值捕获。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-08-14
    • 1970-01-01
    • 2020-02-13
    • 1970-01-01
    • 2020-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多