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

val*_*loh 7 c++ lambda const capture c++11

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

int a;

auto compile_error = [=]()
{
  a = 1;
}
auto compiles_ok = [&]()
{
  a = 1;
}
Run Code Online (Sandbox Code Playgroud)

对我来说,这似乎不合逻辑,但它似乎是标准的?特别是因为捕获值的不需要的修改可能是令人讨厌的错误,但是后果仅限于lambda范围的可能性很高,而通过引用捕获的对象的不需要的修改通常会导致更严重的影响.

那么为什么不默认使用const引用?或者至少支持[const&]和[&]?这个设计的原因是什么?

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

Nev*_*vin 7

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

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

这个lambda相当于:

struct lambda {
    int* p;
    lambda(int* p_) : p(p_) {}
    void operator()() const { ++*p; }
};
Run Code Online (Sandbox Code Playgroud)

constoperator()()使得使用p等于宣告它作为:

int* const p;
Run Code Online (Sandbox Code Playgroud)

类似的事情发生在一个参考.引用本身是"const"(在引号中,因为引用不能重新引用),但是引用它引用的对象不是.


new*_*cct 3

捕获的参考文献也是const。或者更确切地说,引用总是隐式的const——语言中没有语法允许您更改引用指向的位置。a = 1;a是引用时,不是改变引用,而是改变引用所引用的东西。

当你谈论“const引用”时,我认为你很困惑。您正在谈论“对 const int 的引用”( const int &)。那里的“const”指的是引用所指向的东西,而不是引用本身。它与指针类似:对于“指向 const int 的指针”( const int *),指针本身不是const——您可以将您想要的任何内容分配给这种类型的变量。真正的“常量指针”是int *const. 在这里,您不能分配给这种类型的东西;但你可以修改int它指向的内容。因此,指针或引用的“const”与其所指向的事物的“const”是分开的。您还可以有一个“指向 const int 的 const 指针”:const int *const

  • 当然,我知道引用总是引用同一个对象,我的意思是 const 引用就像引用 const 值(修复了误导性主题)。在多线程(任务窃取系统)上下文中使用 lambda 时,意外写入很容易导致竞争条件。在我看来,c++ 的 const 正确性概念比其他语言(如 c#)有优势,但在 lambda 的上下文中,它似乎有点混乱。我想知道为什么没有简单的方法来使用 const lambda 来显式标记已更改的对象。 (2认同)