在没有捕获列表的情况下访问lambda中的变量

时间:2017-01-24 13:39:45

标签: c++ list variables lambda capture

我想知道为什么我可以在lamdas中使用全局变量(感谢Chris Drew纠正我)以及为什么我不需要捕获它们:

#include <iostream>
#include <vector>
using namespace std;

size_t i = 0;
vector<int> v = {1,2,3};

int main()
{
    auto lambda = [](){i = v.size();};
    lambda();
    cout << i << endl;

    return EXIT_SUCCESS;
}

在这个最小的工作示例中,我访问size_t和向量而不捕获它们。如果它们在main方法中声明,我将不得不这样做。为什么会这样,我如何复制size_t和向量?我尝试使用[=]作为捕获列表,但它不会复制vi

4 个答案:

答案 0 :(得分:3)

按值捕获全局变量的一种方法是使用C ++ 14 generalized lambda captures

#include <iostream>
#include <vector>

size_t i = 0;
std::vector<int> v = {1,2,3};

int main() {
    auto lambda = [myi = i, myv = v]()mutable{myi = myv.size();};
    lambda();
    std::cout << i << std::endl;
}

Live demo.

答案 1 :(得分:2)

在您的情况下,iv是全局变量,整个TU都可以访问。

当您询问如何按值捕获它们时,我认为您应该能够使用[=]或列出变量[i, v]捕获它们,但这会导致错误,因为它们会是只读的,你将分配给lambda体内的i

选项1:
通过ref和v来捕获i(如果这有意义的话......):

#include <iostream>  
#include <vector>  
using namespace std;
int main() {
    size_t i = 0;
    vector<int> v = {1,2,3};
    auto lambda = [&i,v](){i = v.size();};
    lambda();
    cout << i << endl;

    return EXIT_SUCCESS; }

http://ideone.com/fkn4za

选项2:
使用一个可变的lambda并按值捕获(这使得意义更小) 即see this question on SO
请注意,在这种情况下,i也会按值捕获,因此不会分配全局i,保留值== 0。

http://ideone.com/qwlFVv

答案 2 :(得分:2)

Lambdas可以访问全局变量和类中的静态变量,而无需显式捕获它们。如果它是一个局部变量,那么你的程序将是不正确的。

#include <iostream>
#include <vector>
using namespace std;
int main()
{
    size_t i = 0;
    vector<int> v = {1,2,3};
    auto lambda = [](){i = v.size();};   //Error, 
    lambda();
    cout << i << endl;

    return EXIT_SUCCESS;
}

here

与类中的静态变量相同:

#include <iostream>
#include <vector>
using namespace std;

struct S{
    void touch(){ []{ k = 89; }(); }
    static int getK(){ return k; }
private:
    static int k;
};

int S::k = 0;


int main()
{
    S s;
    std::cout << S::getK() << std::endl;
    s.touch();
    std::cout << S::getK() << std::endl;
}

Here

答案 3 :(得分:2)

你的lambda基本上转换为仿函数,它与:

相同
#include <iostream>
#include <vector>
using namespace std;

size_t i = 0;
vector<int> v = {1,2,3};

struct lambda
{
  void operator()() { i = v.size(); }
};

int main()
{
    lambda x;
    x();
    cout << i << endl;

    return EXIT_SUCCESS;
}

正如您所看到的,lambda可以完美地访问任何全局变量,甚至在其名称中,变量全局可访问。

如果iv属于main()的本地,那么我们就会遇到问题,我们必须抓住它们。