提问人:Sami 提问时间:7/23/2020 最后编辑:Sami 更新时间:7/23/2020 访问量:751
Lambda(通过引用与值将 lambda 传递给函数)
Lambda (passing a lambda to a function by reference vs by value)
问:
使用 lambda 创建 std::function 时,std::function 在内部创建 lambda 对象的副本。因此,我们对 fn() 的调用 实际上是在我们的 lambda 副本上执行的,而不是实际的 lambda。
根据上面的陈述,在下面的代码中通过“引用 &”或通过“value”传递 lambda 有什么意义,而 std::function 总是复制 lambda 对象?
换句话说,在下面的代码中,当“invoke”函数的参数通过引用或值传递时,lambda 的哪一部分不会被修改/影响?
#include <iostream>
#include <functional>
void invoke(const std::function<void(void)>& fn) // # PASS LAMBDA BY REFERENCE*********************
{
fn();
}
int main()
{
int i{ 0 };
// Increments and prints its local copy of @i.
auto count{ [i]() mutable {
std::cout << ++i << '\n';
} };
invoke(count);
invoke(count);
invoke(count);
return 0;
}
#include <iostream>
#include <functional>
void invoke(const std::function<void(void)> fn) // # PASS LAMBDA BY VALUE*********************
{
fn();
}
int main()
{
int i{ 0 };
// Increments and prints its local copy of @i.
auto count{ [i]() mutable {
std::cout << ++i << '\n';
} };
invoke(count);
invoke(count);
invoke(count);
return 0;
答:
您正在混合两件事 - 通过引用和转换。
通过引用传递
这大致是 lambda 的实现方式:
struct Lambda{
//Capture by value
Lambda(int i):_i(i){}
void operator()() const{
std::cout << ++_i << '\n';
}
mutable int _i;
};
//BTW const is somewhat redundant
void invoke1(const Lambda fn) // # PASS LAMBDA BY VALUE
{
fn();
}
//Const is important, but not yet.
void invoke2(const Lambda& fn) // # PASS LAMBDA BY REFERENCE
{
fn();
}
int main()
{
int i{ 0 };
// Increments and prints its local copy of @i.
Lambda count{i};
invoke1(count);//1
invoke1(count);//1
invoke1(count);//1
invoke2(count);//1
invoke2(count);//2
invoke2(count);//3
return 0;
}
该代码生成您可能想要的输出。
请注意,用法是完全不正确的,但我这样做是为了编译代码。请参阅链接了解如何做到这一点。mutable
std::function
铸造
正如@Jarod42所写的,lambda 不是一个 ,但它可以通过 的构造函数隐式转换为 1。
这根本不是实现方式,为了允许捕获任何可调用对象,还涉及更多的魔法。但它说明了这一点。std::function
std::function
std::function
#include <iostream>
#include <functional>
struct Lambda{
//Capture by value
Lambda(int i):_i(i){}
void operator()() const{
std::cout << ++_i << '\n';
}
mutable int _i;
};
struct Function{
//Makes a copy.
Function(Lambda lambda):_lambda(std::move(lambda)){}
void operator()() const{
_lambda();
}
Lambda _lambda;
};
void invoke1(const Function fn) // # PASS FUNCTION BY VALUE
{
fn();
}
//Const is very important.
void invoke2(const Function& fn) // # PASS FUNCTION BY REFERENCE
{
fn();
}
int main()
{
int i{ 0 };
// Increments and prints its local copy of @i.
Lambda count{i};
invoke1(count);//1
invoke1(count);//1
invoke1(count);//1
invoke2(count);//1
invoke2(count);//1
invoke2(count);//1
return 0;
}
所有调用仍会打印,因为在每次调用时都会创建一个新对象,该对象会创建自己的 lambda 对象的本地副本。当然,电话也发生了同样的情况,但这没有区别,因为无论哪种方式都会进行复制。invoke2
1
Function
count
invoke1
请注意,const in 是非常重要的,没有它,调用将导致编译错误。这是因为允许参数同时绑定到 L 值和 R 值(~temporaries)。invoke2(const Function&)
const Function&
评论
std::function
std::function
std::function
评论
std::function
std::function
template <typename Func> void invoke(const Func &func);
lambda
std::function
void foo(const std::string&)
void foo(std::string)
const char*