C++中使用std::ref在算法中传递lambda的原理是什么?
关于可调用对象的引用传递问题
1. 引用传递在Lambda上的应用逻辑
Lambda表达式在编译阶段会被转换成一个匿名仿函数类,你定义的func其实是这个类的实例。当你通过std::ref(func)传递它的引用时,std::for_each每次调用的都是同一个lambda实例,而非它的副本。
你的代码里,lambda捕获的sum = 0是这个匿名类的成员变量,加上mutable关键字后,允许修改该成员变量。所以std::for_each遍历data的过程中,会持续累加原func实例里的sum值。
2. 代码中被修改的部分
核心修改点是lambda实例的成员变量sum:
- 如果不用
std::ref,std::for_each会复制func的副本,遍历修改的是副本里的sum,原func的sum始终是初始值0,最后调用func(3)会输出3; - 用了
std::ref后,遍历过程修改的是原func实例的sum,累加1+2+3+4+5后sum变为15,再调用func(3)就会输出15+3=18。
3. 仿函数的适用性
完全适用。仿函数本身就是重载了operator()的自定义类实例,和lambda的底层逻辑一致。如果你传递仿函数的引用给算法(比如std::for_each),算法调用时会直接修改原仿函数实例的成员变量,而非副本的。
举个仿函数的等价例子:
#include <iostream> #include <array> #include <algorithm> #include <functional> struct Accumulator { int sum = 0; int operator()(int value) { sum += value; return sum; } }; int main() { std::array<int,5> data{1,2,3,4,5}; Accumulator acc; std::for_each(data.begin(), data.end(), std::ref(acc)); std::cout << acc(3) << '\n'; // 输出18,和你的lambda代码效果一致 }
内容的提问来源于stack exchange,提问作者sam
相关产品推荐
相关产品推荐

