【问题标题】:C++ lambda & std::function capture by value memory management? [duplicate]C++ lambda & std::function 通过值内存管理捕获? [复制]
【发布时间】:2015-10-16 12:40:33
【问题描述】:

lambdas 和 std::functions 在哪里存储按值捕获的变量?

int i = 1;
auto l = [i](void) mutable { return i++; };
std::function<int(void)> f = l;

他们打电话给新的接线员吗?如果我提供自己的 new 运算符,它会被 lambdas 使用吗?

【问题讨论】:

  • Lambda 是将变量保存为成员数据的类,std::function 只是保存 lambda。根据可调用对象的大小,它要么适合std::function,要么位于堆上。

标签: c++ memory-management lambda new-operator


【解决方案1】:

来自 [expr.prim.lambda] 5.1.2(15)

如果实体被隐式捕获并且捕获默认值为 =,或者如果使用非 & 标识符或 & 标识符初始化程序形式的捕获显式捕获实体,则该实体被复制捕获。 对于通过副本捕获的每个实体,在闭包类型中声明一个未命名的非静态数据成员。这些成员的声明顺序是未指定的。如果实体不是对对象的引用,则此类数据成员的类型是相应捕获实体的类型,否则为引用类型。 [注:如果 捕获的实体是对函数的引用,对应的数据成员也是对函数的引用。 ——尾注]不得抄袭匿名工会的成员。

强调我的

所以通过值捕获的变量将被存储为闭包类型的成员。根据 5.1.2(3) 未指定闭包类型

lambda 表达式的类型(也是闭包对象的类型)是唯一的、未命名的非联合类类型——称为闭包类型——其属性如下所述。此类类型既不是聚合(8.5.1)也不是文字类型(3.9)。闭包类型在包含相应 lambda 表达式的最小块作用域、类作用域或命名空间作用域中声明。

【讨论】:

    【解决方案2】:

    在编译时,lambdas 实际上变成了类。因此,如果您有以下情况。

    int a; Widget widget; 
    
    auto somelambda = [=a,&widget](){
    
    }
    

    你实际上可以认为它是

    class SomeLambda
    {
    int a;
    Widge& w;
    ...
    }
    

    这应该让你非常谨慎,因为你可以有悬空的引用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-15
      • 1970-01-01
      • 2014-10-22
      • 2015-03-24
      • 1970-01-01
      相关资源
      最近更新 更多