【问题标题】: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 test{1};
  testFunc(test);
}

【问题讨论】:

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

标签: c++ c++11 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 捕获实体 使用不包含 & 的捕获捕获。对于通过副本捕获的每个实体,一个未命名的非静态 数据成员在闭包类型中声明。这些成员的声明顺序是未指定的。 如果实体不是 引用一个对象,或引用的类型,否则。 [ 注意:如果捕获的实体是对 函数,对应的数据成员也是对函数的引用。 —尾注]

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

【讨论】:

  • 索赔的任何参考资料(如规范中的章节和段落编号)?
  • 我认为重要的原因是存在按值捕获,因此只要闭包存在,变量就有效。如果没有剥离引用,这将不起作用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-15
相关资源
最近更新 更多