为什么我们可以避免在 lambda 捕获中指定类型?
Why can we avoid specifying the type in a lambda capture?
为什么变量 'n' 在 std::generate
的第二次使用中和在 lambda 捕获中没有在下面的代码中以它的数据类型开头?
我认为指定我们在 C++ 代码中使用的所有标识符的数据类型很重要。
#include <algorithm>
#include <iostream>
#include <vector>
int f()
{
static int i;
return ++i;
}
int main()
{
std::vector<int> v(5);
auto print = [&] {
for (std::cout << "v: "; auto iv: v)
std::cout << iv << " ";
std::cout << "\n";
};
std::generate(v.begin(), v.end(), f);
print();
// Initialize with default values 0,1,2,3,4 from a lambda function
// Equivalent to std::iota(v.begin(), v.end(), 0);
std::generate(v.begin(), v.end(), [n = 0] () mutable { return n++; });
print();
}
Why is the variable 'n' in 2nd usage of std::generate and within lambda capture not preceded with it's data type in below code?
它前面没有数据类型,因为 C++ 的语法规定它不需要 - 甚至不允许 - 前面有类型名称。
不需要类型名称,因为类型是从初始化表达式的类型推导出来的。
来自 cppreference:
A capture with an initializer acts as if it declares and explicitly captures a variable declared with type auto, whose declarative region is the body of the lambda expression (that is, it is not in scope within its initializer), [...]
Lambdas 利用无论如何都是新鲜的语法的机会来正确处理某些事情,并允许使用简洁的语法。例如 lambdas operator()
是 const
并且您需要通过 mutable
选择退出而不是默认的非常量成员函数。
No auto
在这个地方不会产生任何问题或歧义。来自 cppreference 的示例:
int x = 4;
auto y = [&r = x, x = x + 1]()->int
{
r += 2;
return x * x;
}(); // updates ::x to 6 and initializes y to 25.
从 lambda 语法可以清楚地看出,&r
是由 x
初始化的按引用捕获,而 x
是由 x + 1
初始化的按值捕获。类型可以从初始值设定项中推导出来。要求添加 auto
.
不会有任何好处
In my experience n could have been just declared inside the lambda body with auto or int as datatype. Isnt it?
是的,但它需要 static
。这会在您的示例中产生相同的输出:
std::generate(v.begin(), v.end(), [] () mutable {
static int n = 0;
return n++; });
但是,捕获可以被认为比局部静态函数更干净。
为什么变量 'n' 在 std::generate
的第二次使用中和在 lambda 捕获中没有在下面的代码中以它的数据类型开头?
我认为指定我们在 C++ 代码中使用的所有标识符的数据类型很重要。
#include <algorithm>
#include <iostream>
#include <vector>
int f()
{
static int i;
return ++i;
}
int main()
{
std::vector<int> v(5);
auto print = [&] {
for (std::cout << "v: "; auto iv: v)
std::cout << iv << " ";
std::cout << "\n";
};
std::generate(v.begin(), v.end(), f);
print();
// Initialize with default values 0,1,2,3,4 from a lambda function
// Equivalent to std::iota(v.begin(), v.end(), 0);
std::generate(v.begin(), v.end(), [n = 0] () mutable { return n++; });
print();
}
Why is the variable 'n' in 2nd usage of std::generate and within lambda capture not preceded with it's data type in below code?
它前面没有数据类型,因为 C++ 的语法规定它不需要 - 甚至不允许 - 前面有类型名称。
不需要类型名称,因为类型是从初始化表达式的类型推导出来的。
来自 cppreference:
A capture with an initializer acts as if it declares and explicitly captures a variable declared with type auto, whose declarative region is the body of the lambda expression (that is, it is not in scope within its initializer), [...]
Lambdas 利用无论如何都是新鲜的语法的机会来正确处理某些事情,并允许使用简洁的语法。例如 lambdas operator()
是 const
并且您需要通过 mutable
选择退出而不是默认的非常量成员函数。
No auto
在这个地方不会产生任何问题或歧义。来自 cppreference 的示例:
int x = 4; auto y = [&r = x, x = x + 1]()->int { r += 2; return x * x; }(); // updates ::x to 6 and initializes y to 25.
从 lambda 语法可以清楚地看出,&r
是由 x
初始化的按引用捕获,而 x
是由 x + 1
初始化的按值捕获。类型可以从初始值设定项中推导出来。要求添加 auto
.
In my experience n could have been just declared inside the lambda body with auto or int as datatype. Isnt it?
是的,但它需要 static
。这会在您的示例中产生相同的输出:
std::generate(v.begin(), v.end(), [] () mutable {
static int n = 0;
return n++; });
但是,捕获可以被认为比局部静态函数更干净。