C++:从外部更改在 lambda 中捕获的变量
C++: Change variables captured in lambda from outside
有什么方法可以从外部在 lambda 中通过复制 来更改捕获的变量?
示例:
#include <iostream>
int main() {
int x = 3;
auto f = [x]() { std::cout << x << std::endl; };
// is there anything I can do here to make f print 4?
f();
}
如果可以的话,感觉真的很脏。有什么令人信服的理由让我什至不应该考虑这样做吗?
#include <iostream>
int main()
{
int x = 3;
auto f = [&x]() { std::cout << x << std::endl; };
x++;
f();
}
struct do_nothing{ template<class...Args> void operator()(Args&&...)const{}};
template<class...cmd>
struct maybe_run_t;
template<> struct maybe_run_t<>:do_nothing{};
template<class cmd>struct maybe_run_t<cmd>{
cmd&& value;
template<class...Args>
void operator()(Args&&...args)const{
value(std::forward<Args>(args)...);
}
};
template<class...Args>
maybe_run_t<Args...> maybe_run(Args&&...args){
return {std::forward<Args>(args)...};
}
然后:
int x = 3;
auto f = [x](auto&&...cmd)mutable { maybe_run(cmd...)(x); std::cout << x << std::endl; };
// is there anything I can do here to make f print 4?
f([](auto&x){x=4;});
f();
打印 4\n4\n
.
你有一个可选参数。如果你通过了一个,它就会修改 x
。如果你不这样做,代码就可以工作。
您也可以根据其存在或 return 值进行流量控制。
还原为原始 'lambda' 类型:使用 operator()
创建结构或 class
struct myLambda
{
int x;
myLambda(int x) : x(x) {};
operator() { std::cout << x << '\n'; }
};
为了回答您的问题,不,不可能从外部更改 function/functor(lambda 是什么)的局部变量。
将 lambda 视为 "regular" 函数,但您不知道其名称。就像常规函数一样,您不能从外部更改局部变量值(按值传递的参数),lambda 也不能这样做。这是结果的安全性和可预测性的必要要求。
如果您在需要执行此操作时遇到问题,正如其他人所建议的那样,请使用 [&]
语法。
(存在 https://www.eecs.umich.edu/courses/eecs588.w14/static/stack_smashing.pdf 但我认为这依赖于对 compiler/system 实现的了解并且通常会出现未定义的行为)
在 C++14 中,您可以这样做:
#include<iostream>
int main() {
int x = 0;
auto l = [x]()mutable->decltype(auto){
std::cout << x << std::endl;
return (x);
};
l() = 42;
l();
}
实际上,在 C++11 中也很容易做类似的事情:
auto l = [x]()mutable->decltype(x)&{
std::cout << x << std::endl;
return x;
};
也就是说,您可以通过引用返回来修改复制捕获的变量。
有什么方法可以从外部在 lambda 中通过复制 来更改捕获的变量?
示例:
#include <iostream>
int main() {
int x = 3;
auto f = [x]() { std::cout << x << std::endl; };
// is there anything I can do here to make f print 4?
f();
}
如果可以的话,感觉真的很脏。有什么令人信服的理由让我什至不应该考虑这样做吗?
#include <iostream>
int main()
{
int x = 3;
auto f = [&x]() { std::cout << x << std::endl; };
x++;
f();
}
struct do_nothing{ template<class...Args> void operator()(Args&&...)const{}};
template<class...cmd>
struct maybe_run_t;
template<> struct maybe_run_t<>:do_nothing{};
template<class cmd>struct maybe_run_t<cmd>{
cmd&& value;
template<class...Args>
void operator()(Args&&...args)const{
value(std::forward<Args>(args)...);
}
};
template<class...Args>
maybe_run_t<Args...> maybe_run(Args&&...args){
return {std::forward<Args>(args)...};
}
然后:
int x = 3;
auto f = [x](auto&&...cmd)mutable { maybe_run(cmd...)(x); std::cout << x << std::endl; };
// is there anything I can do here to make f print 4?
f([](auto&x){x=4;});
f();
打印 4\n4\n
.
你有一个可选参数。如果你通过了一个,它就会修改 x
。如果你不这样做,代码就可以工作。
您也可以根据其存在或 return 值进行流量控制。
还原为原始 'lambda' 类型:使用 operator()
创建结构或 classstruct myLambda
{
int x;
myLambda(int x) : x(x) {};
operator() { std::cout << x << '\n'; }
};
为了回答您的问题,不,不可能从外部更改 function/functor(lambda 是什么)的局部变量。
将 lambda 视为 "regular" 函数,但您不知道其名称。就像常规函数一样,您不能从外部更改局部变量值(按值传递的参数),lambda 也不能这样做。这是结果的安全性和可预测性的必要要求。
如果您在需要执行此操作时遇到问题,正如其他人所建议的那样,请使用 [&]
语法。
(存在 https://www.eecs.umich.edu/courses/eecs588.w14/static/stack_smashing.pdf 但我认为这依赖于对 compiler/system 实现的了解并且通常会出现未定义的行为)
在 C++14 中,您可以这样做:
#include<iostream>
int main() {
int x = 0;
auto l = [x]()mutable->decltype(auto){
std::cout << x << std::endl;
return (x);
};
l() = 42;
l();
}
实际上,在 C++11 中也很容易做类似的事情:
auto l = [x]()mutable->decltype(x)&{
std::cout << x << std::endl;
return x;
};
也就是说,您可以通过引用返回来修改复制捕获的变量。