C ++:从外部更改lambda中捕获的变量

时间:2016-12-06 22:07:41

标签: c++ lambda c++17

有没有办法从外部更改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();
}

如果可以的话,感觉真的很脏。有没有令人信服的理由我为什么不考虑这样做呢?

5 个答案:

答案 0 :(得分:1)

#include <iostream>

int main()
{
    int x = 3;
    auto f = [&x]() { std::cout << x << std::endl; };
    x++;
    f();
}

答案 1 :(得分:1)

要回答你的问题,不能从外面改变函数/函子的局部变量(这是lambda的局部变量)。

将lambda视为“常规”函数,其名称是您没有的。就像常规函数一样,你不能从外部改变局部变量值(通过值传递的参数),你也不能用lambda来做。这是安全性和安全性的必要条件。结果的可预测性。

如果您遇到需要执行此操作的问题,则其他人建议使用[&]语法。

(存在https://www.eecs.umich.edu/courses/eecs588.w14/static/stack_smashing.pdf,但我认为这依赖于编译器/系统实现的知识,并且通常会进入未定义的行为)

答案 2 :(得分:0)

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。如果不这样做,代码就可以运行。

您还可以根据其存在或返回值进行流量控制。

答案 3 :(得分:0)

恢复原始的“lambda”类型:使用operator()

创建结构或类
struct myLambda
{
    int x;
    myLambda(int x) : x(x) {};
    operator() { std::cout << x << '\n'; }
};

答案 4 :(得分:0)

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

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