Lambda:为什么按值捕获的值是 const,而按引用捕获的值不是?

2022-01-23 00:00:00 lambda constants c++ c++11 capture

为什么按值捕获的值是 const,而按引用捕获的对象不是:

Why are captured-by-value values const, but captured-by-reference objects not:

int a;

auto compile_error = [=]()
{
  a = 1;
}
auto compiles_ok = [&]()
{
  a = 1;
}

对我来说这似乎不合逻辑,但它似乎是标准?尤其是对捕获的值进行不必要的修改可能是一个烦人的错误,但结果很可能仅限于 lambda 范围,而对通过引用捕获的对象进行不必要的修改通常会导致更严重的影响.

To me this seem illogical but it seem to be the standard? Especially as the unwanted modification of a captured value may be an annoying bug, but chances are high that the consequences are limited to lambda scope, whereas unwanted modification of objects captured by reference will often lead to more serious effects.

那么为什么不默认通过 const 引用捕获呢?或者至少支持 [const &] 和 [&]?这种设计的原因是什么?

So why not capture by const reference per default? Or at least support [const &] and [&]? What are the reasons for this design?

作为解决方法,您可能应该使用 std::cref 包装的由值捕获的 const 引用?

As workaround you are probably supposed to use std::cref wrapped const references captured by value?

推荐答案

假设您正在按值捕获指针.指针本身是 const,但访问它指向的对象却不是.

Let's say you are capturing a pointer by value. The pointer itself is const, but access to the object it points to is not.

int i = 0;
int* p = &i;
auto l = [=]{ ++*p; };
l();
std::cout << i << std::endl;  // outputs 1

这个 lambda 等效于:

This lambda is equivalent to:

struct lambda {
    int* p;
    lambda(int* p_) : p(p_) {}
    void operator()() const { ++*p; }
};

operator()() 上的 const 使得 p 的使用相当于将其声明为:

The const on the operator()() makes usage of p equivalent to declaring it as:

int* const p;

引用也会发生类似的事情.引用本身是const"(用引号括起来,因为引用不能被重新定位),但不能访问它所引用的对象.

Similar thing happens with a reference. The reference itself is "const" (in quotes because references cannot be reseated), but access to the object it refers to is not.

相关文章