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;
};

也就是说,您可以通过引用返回来修改复制捕获的变量。