Vor*_*rac 8 c++ lambda const c++11
#include <iostream>
int foo(int i)
{
const auto a = [&i](){ i = 7; return i * i; };
a();
return i;
}
int main()
{
std::cout << foo(42) << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这个compiles(g++ -std=c++11 -Wall -Wextra -Wpedantic main.cpp)并返回7.这对我来说是令人惊讶的,因为通过声明a是一个常量对象,我本来希望i被引用为const int&.显然不是,为什么?
[&i](){ i = 7; return i * i; }
Run Code Online (Sandbox Code Playgroud)
主要相当于
class Lambda
{
public:
Lambda(int& arg_i) : i(arg_i) {}
auto operator() () const { i = 7; return i * i;}
private:
int& i;
};
Run Code Online (Sandbox Code Playgroud)
所以你有:
const Lambda a(i);
a();
Run Code Online (Sandbox Code Playgroud)
并const Lambda不会促进其成员,const int& i;但int& const i;相当于int& i;.
小智 7
Lambdas就像非lambdas一样,除了隐藏它们的实现细节.因此,使用非lambda仿函数解释可能更容易:
#include <iostream>
int foo(int i)
{
struct F {
int &i;
int operator()() const { i = 7; return i * i; }
};
const F a {i};
a();
return i;
}
int main()
{
std::cout << foo(42) << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
F有一个int &参考成员i.const F不能修改其实例数据,但修改i不是对其实例数据的修改.对其实例数据的修改将重新绑定i到另一个对象(无论如何都不允许).
当你捕获时,i它被捕获为它的类型.
所以在内部它有一个int&.闭包的变量声明之前的const不会改变lambda的任何内容.
您有2个选项可以解决此问题:
const int i = 5;
auto b = [&i]() { i++; }; //error on i++
Run Code Online (Sandbox Code Playgroud)
这样const int&就可以捕获一个.
如果i由于某些原因无法更改,可以在c ++ 14中执行此操作
int i = 5;
auto b = [i = static_cast<const int&>(i)]() { i++; }; //error on i++
Run Code Online (Sandbox Code Playgroud)
这会将其转换int&为a const int&并将其存储在lambda中.虽然你可以看到这种方式更加冗长.