在没有捕获列表的情况下访问 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 和矢量?我尝试使用 [=]
作为捕获列表,但它不会复制 v
和 i
.
在你的情况下 i
和 v
是全局变量,整个 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; }
选项 2:
使用可变的 lambda 并按值捕获两者(这更没有意义)。
IE。 see this question on SO.
请注意,在这种情况下,i
也会被值捕获,因此全局 i
不会被分配,保持在值 == 0.
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
可以完美访问任何全局变量,甚至在他们的名字中,变量是全局可访问的。
如果 i
和 v
在 main()
本地,那么我们就会遇到问题,我们必须捕获它们。
按值捕获全局变量的一种方法是使用 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;
}
我想知道为什么我可以在 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 和矢量?我尝试使用 [=]
作为捕获列表,但它不会复制 v
和 i
.
在你的情况下 i
和 v
是全局变量,整个 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; }
选项 2:
使用可变的 lambda 并按值捕获两者(这更没有意义)。
IE。 see this question on SO.
请注意,在这种情况下,i
也会被值捕获,因此全局 i
不会被分配,保持在值 == 0.
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
可以完美访问任何全局变量,甚至在他们的名字中,变量是全局可访问的。
如果 i
和 v
在 main()
本地,那么我们就会遇到问题,我们必须捕获它们。
按值捕获全局变量的一种方法是使用 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;
}