C++ 通用兰博达斯

C++ 通用兰博达斯,c++,lambda,c++14,auto,generic-lambda,C++,Lambda,C++14,Auto,Generic Lambda,这行代码(代码1)之间的区别是什么 有时int变量“l”在调用之间共享,有时则不共享。有一个lambda参数的auto,它会创建多个lambda实例吗?我不能完全确定(代码1)与(代码2)有何不同,以及(代码2)与(代码3)有何不同。我期望(代码3)创建多个lambda实例,这样输出将是(Joe 1,Joe 2,1.5 1),但结果是(Joe 1,Joe 2,1.5 3)。在第一个示例中,静态变量的数量与lambda实例的数量一样多。其中可能有很多,因为您将参数指定为auto,这使lambda成

这行代码(代码1)之间的区别是什么


有时int变量“l”在调用之间共享,有时则不共享。有一个lambda参数的auto,它会创建多个lambda实例吗?我不能完全确定(代码1)与(代码2)有何不同,以及(代码2)与(代码3)有何不同。我期望(代码3)创建多个lambda实例,这样输出将是(Joe 1,Joe 2,1.5 1),但结果是(Joe 1,Joe 2,1.5 3)。

在第一个示例中,静态变量的数量与lambda实例的数量一样多。其中可能有很多,因为您将参数指定为
auto
,这使lambda成为某种模板

第三个代码在每次创建lambda时按值捕获
l
,并创建lambda的本地副本,因此不共享任何内容

让我们看一个例子。让我们使用内部定义的lambda创建一个函数
f()
,并调用该函数两次:

void f() {
    //auto l1 = ...

    l1(1);
    l1(2);
    l1(3);
    l1('a');
    l1('b');
    l1('c');
}

f();
std::cout << "---" << std::endl;
f();
f()
的第二个调用允许您重用静态变量,但是对于两种不同的类型,有两个不同的变量

代码2:l是唯一的静态变量,在所有lambda之间共享:

    1 1
    2 2
    3 3
    a 4
    b 5
    c 6
    ---
    1 7
    2 8
    3 9
    a 10
    b 11
    c 12
代码3:每个函数调用创建一个lambda,此lambda使用创建时捕获的变量l的唯一实例:

    1 1
    2 2
    3 3
    a 4
    b 5
    c 6
    ---
    1 1
    2 2
    3 3
    a 4
    b 5
    c 6
如果再次运行此代码,您将看到再次创建
l
,结果将重复

有一个lambda参数的auto,它会创建多个lambda实例吗

它不会创建多个lambda实例,但是lambda将有一个模板化的
操作符()
,以及多个不同类型的实例

对于第一种情况,当使用
const char*
调用两次时,将打印出相同的
静态变量
l
(在类型
const char*
操作符()的实例化中定义)。使用
double
调用时,会打印
静态变量
l
(在类型
double
操作符()的实例化中定义),因此

Joe 1
Joo 2
1.5 1
Joe 1
Joo 2
1.5 3
Joe 1
Joo 2
1.5 3
对于第二种情况,它们都引用在lambda中定义的相同变量
l
,然后您将得到

Joe 1
Joo 2
1.5 1
Joe 1
Joo 2
1.5 3
Joe 1
Joo 2
1.5 3
对于第三种情况,它们都引用lambda捕获的相同变量
l
(甚至调用
operator()
get的不同实例化),然后

Joe 1
Joo 2
1.5 1
Joe 1
Joo 2
1.5 3
Joe 1
Joo 2
1.5 3
对于此版本:

auto l1 = [](auto a) { static int l = 0; std::cout << a << " " << ++l << std::endl; };
static int l = 0;
auto l1 = [](auto a) {  std::cout << a << " " << ++l << std::endl; };

对于此版本:

auto l1 = [](auto a) { static int l = 0; std::cout << a << " " << ++l << std::endl; };
static int l = 0;
auto l1 = [](auto a) {  std::cout << a << " " << ++l << std::endl; };


第三个版本与第二个版本具有相同的效果,只是变量
l
需要在函数局部范围内声明。

代码1 vs代码2

static int l = 0;
auto l1 = [](auto a) {  std::cout << a << " " << ++l << std::endl; };
代码1和2之间的区别只是实例化变量
l
内部与外部的λ。不能保证代码2会看到
l
,您肯定不应该更新
l
,因为lambda没有捕获它

代码2对代码3

int l = 0;
auto l1 = [l](auto a) mutable {  std::cout << a << " " << ++l << std::endl; };
这里的区别在于您已经捕获了
l
[l]
,这意味着lambda可以在其范围内访问该变量。您还将lambda定义为
mutable
,这意味着您可以更新已捕获的变量(
l


代码3是正确的版本。由于您试图访问和更新变量
l
,因此需要捕获它
[l]
,并将lambda定义为可变的,以便更新它。

lambda基本上只是声明函子的一种简单方法。此代码:

#include <iostream>

auto l1 = [](auto a) { static int l = 0; std::cout << a << " " << ++l << std::endl; };

static int m = 0;
auto l2 = [](auto a) {  std::cout << a << " " << ++m << std::endl; };

int n = 0;
auto l3 = [n](auto a) mutable {  std::cout << a << " " << ++n << std::endl; };

int main(){
    l1("Joe");
    l1("Joo");
    l1(1.5);
    std::cout << "\n";
    l2("Joe");
    l2("Joo");
    l2(1.5);
    std::cout << "\n";
    l3("Joe");
    l3("Joo");
    l3(1.5);
}
#包括

自动l1=[](自动a){static int l=0;std::cout代码1

auto l1 = [](auto a) { static int l = 0; std::cout << a << " " << ++l << std::endl; };
    l1("Joe");
    l1("Joo");
    l1(1.5);
autoL1=[](autoA){static int l=0;std::cout
class _tmp_lambda
private:
static int l = 0; /// <--
public: 
{
 _tmp_lambda() {}
 void operator()(const char * a) const
 {
         std::cout << a << " " << ++l << std::endl;
 }
 void operator()(double a) const
 {
         std::cout << a << " " << ++l << std::endl;
 }
};
int l = 0;
auto l1 = [l](auto a) mutable {  std::cout << a << " " << ++l << std::endl; };
class _tmp_lambda
private:
int l = 0; /// <--
public: 
{
 _tmp_lambda(int _l):l(_l) {}
 void operator()(const char * a) // Not a const 
 {
         std::cout << a << " " << ++l << std::endl;
 }
 void operator()(double a) // Not a const
 {
         std::cout << a << " " << ++l << std::endl;
 }
};