繁体   English   中英

C ++ Lambda函数关闭-内存问题

[英]C++ Lambda Function closure - memory issue

我是cpp的新手,正在尝试使用lambda函数。 我有一个计数器,我想在lambda函数内部和外部进行递增。 我看到一些奇怪的记忆错误,我无法理解。 这是我处理此计数器的流程。 我做错了什么吗?

bool SomeClass::func() {
     int64_t counter = 0;

     //some loop logic {
         counter++;
     }


     auto lamb = [this, &counter]() {
        //some logic
        counter++;
     }

     someotherFunction(data, lamb); // this function will execute the lambda

}

问题在于,C ++ lambda无法解决“ upper funarg ”问题,即,当通过lambda通过引用捕获了局部变量时,该lambda 保留了局部“所有者”(因为它存储在某个地方或因为它作为函数返回)结果)。

当lambda通过引用捕获变量时,C ++所做的只是将引用变量的地址存储在lambda代码使用的上下文结构中。

但是,在您的情况下,变量本身是局部变量,并且位于创建lambda的堆栈框架中。 如果只是在执行someOtherFunction过程中调用了lambda对象,那么一切就很好了,但是如果lambda被存储了下来并在创建它的堆栈框架中生存了(或更精确地说,是创建了lambda中引用的捕获变量),当它执行时,将引用一个不再存在的变量(未定义的行为)。

解决一般情况下的“向上funarg”问题需要使用垃圾收集器,而C ++没有垃圾收集器。

在某些情况下,您可以做的是“按值”捕获,因此lambda将拥有自己的私有副本:

foo([counter]() mutable { counter++; })

但是,在这种情况下,如果您想更改捕获的副本,则还需要使用mutable关键字,因为……好吧,这正是C ++在您要修改捕获的副本时所需要的(捕获的副本否则为const对象)。 lambda的主体)。

不幸的是,如果您需要与两个lambda共享捕获的变量(例如,在同一捕获的变量上同时创建“增量器”和“减量器”),则使用副本是不可行的。 为此,您可以通过将std::shared_ptr值捕获到变量中来进行捕获,这将在简单情况下正确替换垃圾收集器(但是,在引用循环的情况下则不然)。

为6502的出色答案添加实用的方法:

auto make_counter(int initial) {
  return [initial] (void) mutable {
    return ++initial;
  };
}

在这里,局部变量(实际上是一个函数参数,但并不重要)是通过值捕获的,这意味着在该lambda的每个对象内部都有一个副本。 为了能够增加计数器,lambda必须允许对其捕获变量进行修改,从而使mutable

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM