lambda 捕获中声明的变量的类型推导
Type deduction for variable declared in lambda's capture
在这段代码中,我在 lambda 的捕获中声明了一个变量 i
。
int main()
{
vector<int> vec;
// Pushing 0-99 numbers to vector
std::generate_n(std::back_inserter(vec), 100, [i = 0]() mutable { return i++; });
return 0;
}
如您所见,i
.
的任何地方都没有声明类型
据我所知,我可以用这种方式编写等效的功能:
int main()
{
vector<int> vec;
// Pushing 0-99 numbers to vector
std::generate_n(std::back_inserter(vec), 100, [](){
static int i = 0;
return i++; });
return 0;
}
编译器如何知道第一个例子中i
的类型?是从我对其执行的操作推导出来的(++)吗?它知道它是 int
是因为容器吗?
使用带有 -std=c++14 和 -std=c++17 的 GCC 编译时没有任何抱怨。
尽管如此,如果我使用 -std=c++11 编译,我会收到以下警告:
lambda_test.cpp: In function ‘int main()’:
lambda_test.cpp:24:51: warning: lambda capture initializers only available with -std=c++14 or -std=gnu++14
std::generate_n(std::back_inserter(first), 100, [i = 0]() mutable { return i++; });
^
MORE:鉴于评论,我试图查看编译器为 c++11 和 14 生成的内容的差异,但它生成相同的代码:
https://cppinsights.io/s/43411e6f
如错误所述,您必须激活 C++14 才能使 lambda 捕获初始化器工作,因为它是在 C++14 中添加的。
As far as I know, I can write the equivalent functionality in this way:
不,静态存储在功能上是不同的。使用捕获,您可以复制 lambda,它将复制捕获的状态。使用静态变量,每个 lambda 访问相同的全局变量。
How does the compiler know the type of i in the first example? Is it deduced from the operation I perform on it (++) ? Does it know that it is int because of the container?
不,因为许多类型都有 ++ 运算符。
编译器简单地使用初始化器来推断类型。你可以看到它好像那里有一个隐藏的 auto
:
std::generate_n(std::back_inserter(vec), 100, [/* auto */ i = 0]() mutable { return i++; });
文字 0
的类型为 int
。所以 i
是一个 int
.
从技术上讲,您也可以这样做:
std::generate_n(std::back_inserter(vec), 100, [/* auto */ i = 0ull]() mutable { return i++; });
然后 i
具有类型 unsigned long long
,因为文字 0ull
是该类型。
它就像你做的那样工作
auto i = 0;
如果您不捕获现有变量并且该初始化程序用于确定类型,则必须指定一个初始化程序。
在这段代码中,我在 lambda 的捕获中声明了一个变量 i
。
int main()
{
vector<int> vec;
// Pushing 0-99 numbers to vector
std::generate_n(std::back_inserter(vec), 100, [i = 0]() mutable { return i++; });
return 0;
}
如您所见,i
.
据我所知,我可以用这种方式编写等效的功能:
int main()
{
vector<int> vec;
// Pushing 0-99 numbers to vector
std::generate_n(std::back_inserter(vec), 100, [](){
static int i = 0;
return i++; });
return 0;
}
编译器如何知道第一个例子中i
的类型?是从我对其执行的操作推导出来的(++)吗?它知道它是 int
是因为容器吗?
使用带有 -std=c++14 和 -std=c++17 的 GCC 编译时没有任何抱怨。 尽管如此,如果我使用 -std=c++11 编译,我会收到以下警告:
lambda_test.cpp: In function ‘int main()’:
lambda_test.cpp:24:51: warning: lambda capture initializers only available with -std=c++14 or -std=gnu++14
std::generate_n(std::back_inserter(first), 100, [i = 0]() mutable { return i++; });
^
MORE:鉴于评论,我试图查看编译器为 c++11 和 14 生成的内容的差异,但它生成相同的代码: https://cppinsights.io/s/43411e6f
如错误所述,您必须激活 C++14 才能使 lambda 捕获初始化器工作,因为它是在 C++14 中添加的。
As far as I know, I can write the equivalent functionality in this way:
不,静态存储在功能上是不同的。使用捕获,您可以复制 lambda,它将复制捕获的状态。使用静态变量,每个 lambda 访问相同的全局变量。
How does the compiler know the type of i in the first example? Is it deduced from the operation I perform on it (++) ? Does it know that it is int because of the container?
不,因为许多类型都有 ++ 运算符。
编译器简单地使用初始化器来推断类型。你可以看到它好像那里有一个隐藏的 auto
:
std::generate_n(std::back_inserter(vec), 100, [/* auto */ i = 0]() mutable { return i++; });
文字 0
的类型为 int
。所以 i
是一个 int
.
从技术上讲,您也可以这样做:
std::generate_n(std::back_inserter(vec), 100, [/* auto */ i = 0ull]() mutable { return i++; });
然后 i
具有类型 unsigned long long
,因为文字 0ull
是该类型。
它就像你做的那样工作
auto i = 0;
如果您不捕获现有变量并且该初始化程序用于确定类型,则必须指定一个初始化程序。