C++ :Lambda函数的浅学习

简介: C++ :Lambda函数的浅学习

前言



lambda表达式又被称之为lambda函数,是c++11的新特性,下面我们看一下lambda表达式的参数等说明:

[函数对象参数](操作符重载函数参数)mutable或exception声明->返回值类型{

函数体

}

下面我们说明一下参数类型以及变量截取规则:


1.[函数对象参数]:捕捉列表。捕捉列表总是出现在lambda函数的开始处,[]是lambda函数的引出符,这个必须存在不可以省略。编译器会根据引出符判断接下来的代码是否是Lambda函数。捕捉列表能够捕捉上下文中的变量以供Lambda函数使用。


2.函数对象参数形式列表:


空。没有任何函数对象参数。


=。函数体内可以使用 Lambda 所在范围内所有可见的局部变量(包括Lambda所在类的this),并且是值传递方式(相当于编译器自动为我们按值传递了所有局部变量)。


&。函数体内可以使用 Lambda 所在范围内所有可见的局部变量(包括 Lambda 所在类的 this),并且是引用传递方式相当于是编译器自动为我们按引用传递了所有局部变量)。


this。函数体内可以使用 Lambda 所在类中的成员变量。


a。将 a 按值进行传递。按值进行传递时,函数体内不能修改传递进来的 a 的拷贝,因为默认情况下函数是 const 的,要修改传递进来的拷贝,可以添加 mutable 修饰符。


&a。将 a 按引用进行传递。

a,&b。将 a 按值传递,b 按引用进行传递。


=,&a,&b。除 a 和 b 按引用进行传递外,其他参数都按值进行传递。

&,a,b。除 a 和 b 按值进行传递外,其他参数都按引用进行传递


3.[操作符重载函数参数] : 标识重载的 () 操作符的参数,没有参数时,这部分可以省略,可以连同括号“()”一起省略。


参数可以通过按值(如: (a, b))和按引用 (如: (&a, &b)) 两种方式进行传递。


4.mutable 或 exception 声明 :mutable 可变变量,exception 异常


注:在使用该修饰符时,参数列表不可省略(即使参数为空);


5.[返回值类型] :返回类型,当不需要返回类型时(void),可以省略


6.[函数体] : 函数内容,可以使用上下文的数据。


一、lambda函数实例



#include <iostream>
using namespace std;
int main()
{
    auto func = [](){cout<<"hello Lambda"; };
    func();
}

a40820f917674a67bceb9873f12c23f3.png

在上图中func就是一个lambda函数,我们使用auto来自动获取func的类型,这一步非常重要,当我们定义好lambda函数之后,就可以当正常函数来使用了。[]表示接下来定义lambda函数,正常情况下只要函数体所有return都是同一个类型的话,编译器就会自行判断函数的返回类型,也可以显式的指定lambda函数的返回类型,这就需要用到函数返回值后置的功能,比如下面这个代码:

[]()->int{return 1;}


那么lambda函数有什么用呢?假如我们设计的一个类需要提供函数查询这个类,可能会根据多种情况查询,还有可能两者结合,我们如果为每个情况都写个函数,那么一定显得很冗余,这个时候就可以用lambda函数来实现这个功能,只需要提供一个接口让用户方便的自定义自己的查询方式。


Lambda函数和STL有什么关系呢?lambda函数的引入为STL的使用提供了极大的方便,就比如下面这个例子,以前我们想遍历一个vector的时候是下面这样的:

int main()
{
    vector<int> v;
    v.push_back(1);
    v.push_back(2);
    v.push_back(3);
    v.push_back(4);
    v.push_back(5);
    vector<int>::iterator it = v.begin();
    for(auto ptr = it;ptr!=v.end();ptr++)
    {
      cout<<*ptr;
    }
}


当我们用lambda后变成了这样:

int main()
{
    vector<int> v;
    v.push_back(1);
    v.push_back(2);
    v.push_back(3);
    v.push_back(4);
    v.push_back(5);
   for_each(v.begin(),v.end(),[](int val)
   {
           cout<<val;
   } );
}


我们用lambda表达式这样的写法可以提高代码的执行效率,因为编译器有可能使用"循环展开"来加速执行过程。


总结



lambda 表达式就是一个函数(匿名函数),也就是一个没有函数名的函数。为什么不需要函数名呢,因为我们直接(一次性的)用它,嵌入式用的它,不需要其他地方调用它。lambda表达式也叫闭包。闭就是封闭的意思(封闭就是其他地方都不调用它),包就是函数。lambda表达式其实就是一个函数对象,他内部创建了一个重载()操作符的类。lambda的引入给我们带来了一种全新的编程体验,使我们从繁琐的语法中解放出来,更加关注于 “算法” 本身。

目录
相关文章
|
4天前
|
算法 编译器 C++
【C++11】lambda表达式
C++11 引入了 Lambda 表达式,这是一种定义匿名函数的方式,极大提升了代码的简洁性和可维护性。本文详细介绍了 Lambda 表达式的语法、捕获机制及应用场景,包括在标准算法、排序和事件回调中的使用,以及高级特性如捕获 `this` 指针和可变 Lambda 表达式。通过这些内容,读者可以全面掌握 Lambda 表达式,提升 C++ 编程技能。
27 3
|
29天前
|
编译器 C语言 C++
配置C++的学习环境
【10月更文挑战第18天】如果想要学习C++语言,那就需要配置必要的环境和相关的软件,才可以帮助自己更好的掌握语法知识。 一、本地环境设置 如果您想要设置 C++ 语言环境,您需要确保电脑上有以下两款可用的软件,文本编辑器和 C++ 编译器。 二、文本编辑器 通过编辑器创建的文件通常称为源文件,源文件包含程序源代码。 C++ 程序的源文件通常使用扩展名 .cpp、.cp 或 .c。 在开始编程之前,请确保您有一个文本编辑器,且有足够的经验来编写一个计算机程序,然后把它保存在一个文件中,编译并执行它。 Visual Studio Code:虽然它是一个通用的文本编辑器,但它有很多插
|
1月前
|
程序员 C++ 容器
在 C++中,realloc 函数返回 NULL 时,需要手动释放原来的内存吗?
在 C++ 中,当 realloc 函数返回 NULL 时,表示内存重新分配失败,但原内存块仍然有效,因此需要手动释放原来的内存,以避免内存泄漏。
|
1月前
|
存储 前端开发 C++
C++ 多线程之带返回值的线程处理函数
这篇文章介绍了在C++中使用`async`函数、`packaged_task`和`promise`三种方法来创建带返回值的线程处理函数。
48 6
|
1月前
|
C++
C++ 多线程之线程管理函数
这篇文章介绍了C++中多线程编程的几个关键函数,包括获取线程ID的`get_id()`,延时函数`sleep_for()`,线程让步函数`yield()`,以及阻塞线程直到指定时间的`sleep_until()`。
25 0
C++ 多线程之线程管理函数
|
1月前
|
编译器 C语言 C++
C++入门3——类与对象2-2(类的6个默认成员函数)
C++入门3——类与对象2-2(类的6个默认成员函数)
27 3
|
1月前
|
编译器 C语言 C++
详解C/C++动态内存函数(malloc、free、calloc、realloc)
详解C/C++动态内存函数(malloc、free、calloc、realloc)
191 1
|
1月前
|
存储 编译器 C++
C++入门3——类与对象2-1(类的6个默认成员函数)
C++入门3——类与对象2-1(类的6个默认成员函数)
34 1
|
1月前
|
Java 编译器 C++
c++学习,和友元函数
本文讨论了C++中的友元函数、继承规则、运算符重载以及内存管理的重要性,并提到了指针在C++中的强大功能和使用时需要注意的问题。
22 1
|
1月前
|
编译器 C语言 C++
C++入门6——模板(泛型编程、函数模板、类模板)
C++入门6——模板(泛型编程、函数模板、类模板)
46 0
C++入门6——模板(泛型编程、函数模板、类模板)