我的编程空间,编程开发者的网络收藏夹
学习永远不晚

C++超详细梳理lambda和function的使用方法

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

C++超详细梳理lambda和function的使用方法

lambda表达式

lambda表达式又称为匿名表达式,是C11提出的新语法。[]存储lambda表达式要捕获的值,()内的参数为形参,可供外部调用传值。lambda表达式可以直接调用

 // 1  匿名调用
    [](string name)
    {
        cout << "this is anonymous" << endl;
        cout << "hello " << name << endl;
    }("zack");

上述代码定义了一个匿名函数后直接调用。我们可以通过auto初始化一个变量存储lambda表达式

 // 2 通过auto赋值
    auto fname = [](string name)
    {
        cout << "this is auto  " << endl;
        cout << "hello " << name << endl;
    };
    fname("Rolin");

通过auto定义fname,然后存储了lambda表达式,之后调用fname即可。也可以通过函数指针的方式接受lambda表达式

    typedef void (*P_NameFunc)(string name);
    // 3 函数指针
    P_NameFunc fname2 = [](string name)
    {
        cout << "this is P_NameFunc " << endl;
        cout << "hello " << name << endl;
    };
    fname2("Vivo");

P_NameFunc定义了fname2函数指针接受了lambda表达式。也可以通过function对象接受lambda表达式,function类是C11新增的语法。

// 4 function
    function<void(string)> funcName;
    funcName = [](string name)
    {
        cout << "this is function " << endl;
        cout << "hello " << name << endl;
    };
    funcName("Uncle Wang");

用一个function对象接受了lambda表达式,同样可以调用该function对象funcName达到调用lambda的效果。

谈谈lambda的捕获

1 值捕获

    int age = 33;
    string name = "zack";
    int score = 100;
    string job = "softengineer";
    //值捕获
    [age, name](string name_)
    {
        cout << "age is " << age << " name is " << name << " self-name is " << name_ << endl;
    }("Novia");

上述lambda表达式捕获了age和name,是以值的方式来捕获的。所以无法在lambda表达式内部修改age和name的值,如果修改age和name,编译器会报错,提示无法修改const常量,因为age和name是以值的方式被捕获的。

2 引用捕获

    int age = 33;
    string name = "zack";
    int score = 100;
    string job = "softengineer";
    [&age, &name](string name_)
    {
        cout << "age is " << age << " name is " << name << " self-name is " << name_ << endl;
        name = "Xiao Li";
        age = 18;
    }("Novia");

[]里age和name前边添加了&,此时age和name是以引用方式捕获的。所以可以在lambda表达式中修改age和name的值。

C++的lambda表达式虽然可以捕获局部变量的引用,达到类似闭包的效果,但不是真的闭包,golang和python等语言通过闭包捕获局部变量后可以增加局部变量的声明周期,C++无法做到这一点,所以下面的调用会出现崩溃。

vector<function<void(string)>> vec_Funcs;
void use_lambda2()
{
    int age = 33;
    string name = "zack";
    int score = 100;
    string job = "softengineer";
    vec_Funcs.push_back([age, name](string name_)
                        {   cout << "this is value catch " << endl;
                            cout << "age is " << age << " name is " << name << " self-name is " << name_ << endl; });
    //危险,不要捕获局部变量的引用
    vec_Funcs.push_back([&age, &name](string name_)
                        {   cout << "this is referenc catch" << endl;
                            cout << "age is " << age << " name is " << name << " self-name is " << name_ << endl; });
}
void use_lambda3()
{
    for (auto f : vec_Funcs)
    {
        f("zack");
    }
}
int main(){
    use_lambda2();
    use_lambda3();
}

use_lambda2中将lambda表达式存储在function类型的vector里,当use_lambda2结束后,里边的局部变量都被释放了,而vector中的lambda表达式还存储着局部变量的引用,在调用use_lambda3时调用lambda表达式,此时访问局部变量已经被释放了,所以导致程序崩溃。

3 全部用值捕获,name用引用捕获

    int age = 33;
    string name = "zack";
    int score = 100;
    string job = "softengineer";
    [=, &name]()
    {
        cout << "age is " << age << " name is " << name << " score is " << score << " job is " << job << endl;
        name = "Cui Hua";
    }();

通过=表示所有变量都以值的方式捕获,如果希望某个变量以引用方式捕获则单独在这个变量前加&。

4 全部用引用捕获,只有name用值捕获

   int age = 33;
   string name = "zack";
   int score = 100;
   string job = "softengineer";
   [&, name]()
   {
        cout << "age is " << age << " name is " << name << " score is " << score << " job is " << job << endl;
   }();

通过&方式表示所有变量都已引用方式捕获,如果希望某个变量以值方式捕获则单独在这个变量前加=。

万能的function

我们可以用function存储形参和返回值相同的一类函数指针,可调用对象,lambda表达式等。

void use_function()
{
    list<function<void(string)>> list_Funcs;
    //存储函数对象
    list_Funcs.push_back(FuncObj());
    //存储lambda表达式
    list_Funcs.push_back([](string str)
                         { cout << "this is lambda call " << str << endl; });
    //存储全局函数
    list_Funcs.push_back(globalFun);
    for (const auto &f : list_Funcs)
    {
        f("hello zack");
    }
}

bind操作

C11同样提供了bind操作,将原函数的几个参数通过bind绑定传值,返回一个新的可调用对象。

    //绑定全局函数
    auto newfun1 = bind(globalFun2, placeholders::_1, placeholders::_2, 98, "worker");
    //相当于调用globalFun2("Lily",22, 98,"worker");
    newfun1("Lily", 22);
    //多传参数没有用,相当于调用globalFun2("Lucy",28, 98,"worker");
    newfun1("Lucy", 28, 100, "doctor");
    auto newfun2 = bind(globalFun2, "zack", placeholders::_1, 100, placeholders::_2);
    //相当于调用globalFun2("zack",33,100,"engineer");
    newfun2(33, "engineer");
    auto newfun3 = bind(globalFun2, "zack", placeholders::_2, 100, placeholders::_1);
    newfun3("coder", 33);

placeholders表示占位符,_1表示新生成函数的第一个参数, _2表示新生成函数的第二个参数,将这些参数传递给原函数达到占位的效果,原函数的其余参数通过bind绑定固定值。

接下来定义类

class BindTestClass
{
public:
    BindTestClass(int num_, string name_) : num(num_), name(name_) {}
    static void StaticFun(const string &str, int age);
    void MemberFun(const string &job, int score);
public:
    int num;
    string name;
};

实现静态函数和成员函数

void BindTestClass::StaticFun(const string &str, int age)
{
    cout << "this is static function" << endl;
    cout << "name is " << str << endl;
    cout << "age is " << age << endl;
}
void BindTestClass::MemberFun(const string &job, int score)
{
    cout << "this is member function" << endl;
    cout << "name is " << name << endl;
    cout << "age is " << num << endl;
    cout << "job is " << job << endl;
    cout << "score is " << score << endl;
}

我们通过bind绑定静态成员函数

    //绑定类的静态成员函数,加不加&都可以
    // auto staticbind = bind(BindTestClass::StaticFun, placeholders::_1, 33);
    auto staticbind = bind(&BindTestClass::StaticFun, placeholders::_1, 33);
    staticbind("zack");

新生成的staticbind函数可以直接传递一个参数zack就完成了调用。接下来用bind绑定成员函数

    BindTestClass bindTestClass(33, "zack");
    // 绑定类的成员函数,一定要传递对象给bind的第二个参数,可以是类对象,也可以是类对象的指针
    // 如果要修改类成员,必须传递类对象的指针
    auto memberbind = bind(BindTestClass::MemberFun, &bindTestClass, placeholders::_1, placeholders::_2);
    memberbind("coder", 100);
    auto memberbind2 = bind(BindTestClass::MemberFun, placeholders::_3, placeholders::_1, placeholders::_2);
    memberbind2("coder", 100, &bindTestClass);
    //绑定类成员时,对象必须取地址
    auto numbind = bind(&BindTestClass::num, placeholders::_1);
    std::cout << numbind(bindTestClass) << endl;

当然也可以直接用function对象接受bind返回的结果

    // function接受bind返回的函数
    function<void(int, string)> funcbind = bind(globalFun2, "zack", placeholders::_1, 100, placeholders::_2);
    funcbind(33, "engineer");
    // function接受bind 成员函数
    function<void(string, int)> funcbind2 = bind(BindTestClass::MemberFun, &bindTestClass, placeholders::_1, placeholders::_2);
    funcbind2("docker", 100);
    function<void(string, int, BindTestClass *)> funcbind3 = bind(BindTestClass::MemberFun, placeholders::_3, placeholders::_1, placeholders::_2);
    funcbind3("driver", 100, &bindTestClass);
    // function 直接接受成员函数,function的模板列表里第一个参数是类对象引用
    function<void(BindTestClass &, const string &, int)> functomem = BindTestClass::MemberFun;
    functomem(bindTestClass, "functomem", 88);
    // function 绑定类的静态成员函数
    function<void(const string &)> funbindstatic = bind(&BindTestClass::StaticFun, placeholders::_1, 33);
    funbindstatic("Rolis");

lambda和bind的使用就介绍到这里

源码链接

视频链接

到此这篇关于C++超详细梳理lambda和function的使用方法的文章就介绍到这了,更多相关C++ lambda和function内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

C++超详细梳理lambda和function的使用方法

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

C++超详细梳理lambda和function的使用方法

C++在C11标准中引入了匿名函数,即没有名字的临时函数,又称之为lambda表达式.lambda表达式实质上是创建一个匿名函数/对象,这篇文章主要介绍了lambda和function的使用方法
2022-11-13

C++BoostLockfree超详细讲解使用方法

Boost是为C++语言标准库提供扩展的一些C++程序库的总称。Boost库是一个可移植、提供源代码的C++库,作为标准库的后备,是C++标准化进程的开发引擎之一,是为C++语言标准库提供扩展的一些C++程序库的总称
2022-11-21

C++ Boost Lockfree超详细讲解使用方法

Boost Lockfree 是一个基于 C++ 的库,用于实现无锁的数据结构和算法。无锁的数据结构和算法是为了解决并发编程中的竞争条件和锁竞争而设计的。由于无锁的数据结构和算法可以避免锁竞争,因此在高度并发的场景中,可以提供更好的性能和可
2023-08-16

C++和C#中的lambda方法怎么使用

这篇文章主要讲解了“C++和C#中的lambda方法怎么使用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C++和C#中的lambda方法怎么使用”吧!一、语法定义首先我们看下 C++ 语法
2023-07-02

Python中lambda表达式的简要介绍和详细使用方法

Python中lambda函数的简介与用法详解在Python中,lambda函数是一种特殊的匿名函数,它可以在需要函数对象的任何地方使用。lambda函数通常用来定义一些简单的函数,它们可以只有一个表达式,并且返回结果。本文将向您介绍la
Python中lambda表达式的简要介绍和详细使用方法
2024-02-02

Python中JSON的使用方法(超详细)

JSON是一种轻量级的数据交换格式,它是JavaScript的子集,易于人阅读和编写,这篇文章主要介绍了Python中JSON的基本使用,需要的朋友可以参考下
2022-11-13

C语言 详细讲解#pragma的使用方法

#pragma是C语言中的预处理指令,用于告诉编译器在编译过程中采取特定的行为。以下是#pragma的使用方法的详细讲解:1. #pragma once:这个指令放在头文件的开头,作用是确保头文件只被编译一次,避免重复包含。2. #prag
2023-08-08

C#中TransactionScope的使用方法和原理

在C#中,TransactionScope用于创建一个事务范围,能够确保一系列数据库操作要么全部成功提交,要么全部回滚。TransactionScope采用了分布式事务的机制,可以跨越多个数据库连接、多个数据库以及分布式系统。使用方法:1.
2023-09-01

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录