我们应该在lambda中通过const引用捕获吗?

时间:2018-06-09 22:27:24

标签: c++ c++11 closures c++14 const

我一直在阅读Lambda capture as const reference?
这是一个有趣的功能,有时我也希望这个功能存在,特别是当我有大量数据时,我需要在lambda函数中访问它。

我的后续问题 -

  • 我们应该通过lambda中的const引用来捕获吗?如果是的话,它应该如何表现? (编辑 - 我也对捕获变量的生命周期行为感兴趣。)
  • 通过在C ++语法中引入它是否有任何可能的缺点?(我想不出来)

让我们假设我们可以 我们假设[const &]是要捕获的语法。

int x = 10;
auto lambda = [const & x](){ std::cout << x << std::endl; }; 
lambda(); // prints 10, great, as expected

x = 11;
lambda(); // should it print 11 or 10 ?

我的直觉是应该表现得像[&],但不应该允许修改捕获的值。

template<typename Func>
void higher_order_function(int & x, Func f)
{
    f(); // should print 11
    x = 12;
    f(); // should print 12
}

void foo()
{
    int x = 10;
    auto c = [const & x] () { std::cout << x << std::endl; };

    c(); // should print 10
    x = 11;
    c(); // should print 11
    higher_order_function(x, c);

    auto d = [const & x] () { x = 13; }; // Compiler ERROR: Tried to assign to const qualified type 'const int &'!
} 

3 个答案:

答案 0 :(得分:4)

lambda(); // should it print 11 or 10 ?

我不明白为什么要打印10.考虑lambda只是某个匿名类的实例。使它成为正常的类,它应该看起来像:

class Lambda {
   public:
      Lambda(const int & i) : i_(i) { }
      void operator()() { std::cout << i_ << std::endl; }
   private:
      const int & i_;
 };

int x = 10;
Lambda lambda(x);
lambda(); // prints 10, great, as expected

x = 11;
lambda(); // should it print 11 or 10 ?

此处const引用的含义仅在于您无法通过x成员引用变量修改i_

一个简单的场景:

int x = 10;
const int & crx = x;
x++;
std::cout << crx << std::endl; // prints 11

答案 1 :(得分:2)

我自己一直在想这个。
由于operator()默认是const,我认为允许const引用也是可接受的。

根据现行标准(C ++ 17),我最接近这种行为是:

auto c = [ &x = std::as_const(x) ] () { std::cout << x << std::endl; };

C ++ 11 / C ++ 14中的解决方法(感谢Daniel的建议):

auto const & crx = x;
auto c = [ &crx ] () { std::cout << crx << std::endl; };

答案 2 :(得分:1)

也许不完全是你想要的但是......我想你可以通过const引用传递一个接收相同值的函数。

以下内容

template <typename T>
auto make_capture_const (T const & x)
 { return [&x](){ std::cout << x << std::endl; }; }

// ...

int x { 42 };

auto l = make_capture_const(x);

l();

如果您尝试修改lambda中的x

std::cout << x++ << std::endl;

你应该收到错误。

正如你所看到的,从这个解决方案中你得到的x不能在lambda中修改,但lambda会受到外部值变化的影响

   int x { 42 };

   auto l = make_capture_const(x);

   l();  // print 42

   x = 43;

   l();  // print 43

恕我直言,假设[const &]捕获语法应该以相同的方式工作。但我明白这是非常值得怀疑的。