提问人:matt richards 提问时间:2/26/2022 最后编辑:matt richards 更新时间:2/26/2022 访问量:253
在 C++ 中为 Lambda 创建闭包
create a closure for a lambda in c++
问:
这是为 lambda 函数创建闭包的正确方法吗
#include <functional>
#include <memory>
#include <string>
#include <iostream>
using namespace std;
class A
{
function<void()> fn(string str){ // (2)
struct closure {
int num;
};
auto ptr = make_shared<closure>();
ptr->num = 99;
auto fn = [=](){
ptr->num++;
cout << ptr->num << " -- " << str << endl;
};//fn
return fn;
}//fn
};//A
A a;
int main(){
auto fn = a.fn("1");
fn();
fn();
auto fn2 = a.fn("2");
fn2();
fn2();
}//main
闭包中似乎不需要创建 lambda @(2) 的函数的参数,这真的是真的吗?
使用这种方法有什么注意事项,堆/堆栈 = 奶油,我需要释放内存吗?
在 lambda 中通过引用捕获会产生什么实际影响?
编辑
也许我过度简化了,有时函数看起来像这样
class A {
void fn(string str){
struct closure {
int num;
int token;
};
auto ptr = make_shared<closure>();
ptr->num = 100;
auto fn = [=](){
ptr->num++;
cout << str << ptr->num << endl;
if(ptr->num==105){
list.rem(ptr->token); // <= defined elsewhere
}
};
ptr->token = list.add(fn); // <= defined elsewhere
}//fn
};//A
答:
0赞
Jarod42
2/26/2022
#1
这是为 lambda 函数创建闭包的正确方法吗?
您的 lambda 可以简化为:
function<void()> fn(string str){
return [str, i = 99]() mutable {
++i;
std::cout << i << " -- " << str << std::endl;
};
}
我需要释放内存吗?
你按值捕获一个,它会在销毁时释放它的记忆,你很好。std::shared_ptr
在 lambda 中通过引用捕获会产生什么实际影响?
捕获局部变量时,通过引用捕获将导致悬空指针。
评论
0赞
matt richards
2/26/2022
何时发生销毁 - 当不再引用 lambda 时?
0赞
Jarod42
2/26/2022
shared_ptr
owner 是 lambda,拥有 lambda。因此,当范围 where / are (so in ) 结束时,所有这些东西都会被破坏。std::function
fn
fn2
main
0赞
Chris Uzdavinis
2/26/2022
#2
看起来它没有错,但就其本质而言,它看起来也像是巨大的矫枉过正。
您可以在不使用 sharerd_ptr 或任何动态内存的情况下完成同样的事情,只需捕获 int 并使 lambda 可变:
std::function<void()> fn(std::string str){ // (2)
return [=, num = 99]() mutable {
num++;
std::cout << num << " -- " << str << "\n";
};
}
如果您计划复制 lambda 并让两个副本影响相同的底层数据,或者,您保留该共享指针并用它做更多事情,可能是在返回 lambda 之后,那么您的方法可能更有意义。自定义结构和共享 ptr 很重,我尽可能喜欢简单。
此外,按值/按引用问题也很重要,因为在 lambda 中打印出来,它需要确保它使用的对象继续存在。由于它是一个函数参数,因此当函数返回时,参数将被销毁,因此 lambda 不得存储对它的引用,否则它将是对已破坏的对象的引用,并在调用它时导致未定义的行为。您需要副本来保留字符串,以便在调用 lambda 时保证它有效。str
评论