#include <iostream>
int foo(int i)
{
const auto a = [&i](){ i = 7; };
a();
return i;
}
int main()
{
std::cout << foo(42) << std::endl;
return 0;
}
这将编译(g++ -std=c++11 -Wall -Wextra -Wpedantic main.cpp
)并打印7
。这让我很惊讶,因为通过将a
声明为常量对象,我本来希望i
被引用为const int&
。显然不是,为什么?
6条答案
按热度按时间3gtaxfhh1#
Lambdas就像非Lambdas一样,除了它们的实现细节是隐藏的。因此,使用非lambda函子可能更容易解释:
F
有一个int &
引用成员i
。const F
不能修改其示例数据,但对i
的修改并不是对其示例数据的修改。对其示例数据的修改将把i
重新绑定到另一个对象(这无论如何都是不允许的)。plupiseo2#
主要相当于
然后你有:
const Lambda
不会将其成员 * 提升 * 为const int& i;
,而是int& const i;
,相当于int& i;
。8yoxcaq73#
当你捕获
i
时,它被捕获为它的类型。所以它内部有一个
int&
。闭包的变量声明前的const不会改变lambda的任何内容。你有两个选择来解决这个问题:
这样,将捕获
const int&
。如果由于某些原因不能更改
i
,可以在c++14中进行更改这将
int&
转换为const int&
,并将其存储在lambda中。虽然这是更详细的方式,因为你可以看到。uurv41yg4#
在您提供的代码中:
在初始化常量lambda函数后,您没有进行赋值。因此,
const
在此上下文中没有太大意义。lymnna715#
你声明为
const
的内容不是匿名函数或lambda表达式及其参数的上下文,而只是lambda表达式的引用:const auto a
。因此,您不能更改lambda expr引用
a
的值,因为它是const,但其通过引用传递的参数&i
可以在lambda表达式的上下文中更改。yjghlzjz6#
如果我理解正确的话,问题是为什么允许你改变
i
,即使a
是const
,并且可能包含对i
的引用作为成员。答案是,这与允许对任何对象执行此操作的原因相同--赋值给
i
不会修改lambda示例,它修改的是它引用的对象。示例:
这将编译并打印“99”,因为
foo
没有修改a
的成员,而是修改了e
。(This有点令人困惑,但它有助于思考哪些 * 对象 * 正在被修改,而忽略它们的命名方式。)
const
的这种“const,but not really”性质是非常常见的混淆和烦恼的来源。这正是指针的行为方式,更明显的是它没有错: