为什么我们可以避免在 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++; });

但是,捕获可以被认为比局部静态函数更干净。