在 lambda 中,引用的按值捕获是不是会复制底层对象?

Posted

技术标签:

【中文标题】在 lambda 中,引用的按值捕获是不是会复制底层对象?【英文标题】:In a lambda, does a by-value capture of a reference copy the underlying object?在 lambda 中,引用的按值捕获是否会复制底层对象? 【发布时间】:2013-11-09 16:27:00 【问题描述】:

如果在 lambda 中按值捕获引用类型的变量,是复制引用的对象还是通过引用捕获?

有问题的小样本:

#include <iostream>

struct Test 
  int a;
;

void testFunc(const Test &test) 
  auto a = [=] 
    // is 'test' passed to closure object as a copy
    // or as a reference?
    return test.a;
   ();
  std::cout << a;


int main() 
  Test test1;
  testFunc(test);

【问题讨论】:

那么,测试一下怎么样? (您需要为此修改对象,这可以通过尝试使用非常量引用或通过创建变量 mutable 来实现。) 似乎是value。 @JanHudec 是的,测试很好,但是查看相关标准的部分和基于理论的答案总是有用的(有很多这样的专家)。 知道引用不是对象有帮助吗? Lambda 总是捕获对象,它们可以通过值或引用来实现。 【参考方案1】:

按价值。可编译示例:

class C

public:
    C()
    
        i = 0;
    

    C(const C & source)
    
        std::cout << "Copy ctor called\n";
        i = source.i;
    

    int i;
;

void test(C & c)

    c.i = 20;

    auto lambda = [=]() mutable 

        c.i = 55;
    ;
    lambda();

    std::cout << c.i << "\n";


int main(int argc, char * argv[])

    C c;
    test(c);

    getchar();

结果:

复制 ctor 调用
20

我猜,这一段 C++ 标准适用:

5.1.2 Lambda 表达式

(...) 14. 如果实体被隐式捕获且capture-default 为= 或显式捕获,则copy 捕获实体 使用不包含 & 的捕获捕获。对于通过副本捕获的每个实体,一个未命名的非静态 数据成员在闭包类型中声明。这些成员的声明顺序是未指定的。 如果实体不是 引用一个对象,或引用的类型,否则。 [ 注意:如果捕获的实体是对 函数,对应的数据成员也是对函数的引用。 —尾注]

这实际上是有道理的——如果局部变量是通过值传递的,而通过引用传递的参数“充当”函数中的局部变量,为什么它会通过引用而不是值传递?

【讨论】:

索赔的任何参考资料(如规范中的章节和段落编号)? 我认为重要的原因是存在按值捕获,因此只要闭包存在,变量就有效。如果没有剥离引用,这将不起作用。

以上是关于在 lambda 中,引用的按值捕获是不是会复制底层对象?的主要内容,如果未能解决你的问题,请参考以下文章

java的按值传递与按引用传递

我是不是正确理解了 C 中的按值传递和按引用传递?

输入参数传递:是不是有有效的按值传递的大小阈值?

第18课 捕获机制及陷阱

Java的按值传递和按引用传递解说

第13课 lambda表达式