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

Accessing variables in lambda without capture list

我想知道为什么我可以在 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 和矢量而不捕获它们。如果它们是在主方法中声明的,我将不得不这样做。为什么会这样,如何复制 size_t 和矢量?我尝试使用 [=] 作为捕获列表,但它不会复制 vi.

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

正如您询问如何按值捕获它们一样,我认为您应该能够同时使用 [=] 或列出变量 [i, v] 来捕获它们,但这会导致错误,因为它们将是 read-only 并且您正在分配给 lambda 体内的 i

选项 1:
通过 ref 捕获 i 并通过值捕获 v(如果这完全有意义......):

#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 并按值捕获两者(这更没有意义)。
IE。 see this question on SO.
请注意,在这种情况下,i 也会被值捕获,因此全局 i 不会被分配,保持在值 == 0.

http://ideone.com/qwlFVv

Lambda 可以访问 class 中的全局变量和静态变量,而无需显式捕获它们。如果它是一个局部变量,那么你的程序将是 ill-formed.

#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

与 class 中的静态变量相同:

#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

你的 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可以完美访问任何全局变量,甚至在他们的名字中,变量是全局可访问的。

如果 ivmain() 本地,那么我们就会遇到问题,我们必须捕获它们。

按值捕获全局变量的一种方法是使用 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.