C++11中的lambda、包装器(function、bind)

🐶博主主页:@ᰔᩚ. 一怀明月ꦿ 

❤️‍🔥专栏系列:线性代数C初学者入门训练题解CC的使用文章「初学」C++

🔥座右铭:“不要等到什么都没有了,才下定决心去做”

🚀🚀🚀大家觉不错的话,就恳求大家点点关注,点点小爱心,指点指点🚀🚀🚀

c++11中的lambda表达式

lambda表达式的基本格式

[capture list] (parameters) -> return_type {
    // 函数体
}

* capture-list:用于捕获外部变量,可以省略。捕获方式有三种:

    * [&]:以引用方式捕获所有外部变量。

    * [=]:以值的方式捕获所有外部变量。

    * [var1, var2, ...]:指定需要捕获的外部变量列表,可以使用 & 或 = 来指定捕获方式。

* parameter-list:函数参数列表,类似于普通函数的参数列表,可以省略。

* return-type:返回类型,可以省略,编译器可以自动推断。

* body:Lambda 函数体,类似于普通函数体,包含了执行的语句。

下面是一个简单的示例,展示了如何在 C++11 中使用 Lambda 表达式:

不使用捕捉列表 capture-list

#include <iostream>

int main() {
    // Lambda 表达式示例:计算两个数的和
    //参数列表有两个整数
    auto add = [](int a, int b) -> int {
        return a + b;
    };

    // 调用 Lambda 表达式
    int result = add(3, 4);
    std::cout << "Result of add function: " << result << std::endl;

    // Lambda 表达式示例:打印 Hello World
    //参数列表为空
    auto printHello = []() {
        std::cout << "Hello, World!" << std::endl;
    };

    // 调用 Lambda 表达式
    printHello();

    return 0;
}

使用捕捉列表 capture-list

int main()
{
    int x=119,y=120;

    cout<<"x="<<x<<":"<<"y="<<y<<endl;
    //参数列表为空,调用时不需要传递参数
    auto f1=[&x,&y]()
    {
        int temp;
        temp=x;
        x=y;
        y=temp;
    };//[]就是捕捉列表,可以捕捉lambda表达式所在函数(这里是main函数)里的变量,提供自己使用,这里采用的是引用捕捉x,y,因为我们要在lambda的函数体里修改x,y,如果不需要修改x,y的值时,可以采用值捕捉[x,y](){}

    f1();
    cout<<"x="<<x<<":"<<"y="<<y<<endl;
    return 0;
}

使用捕捉列表 capture-list的其他用法

int main()
{
    int x = 1,y = 2,z = 3;
    //以值的方式捕捉所有的变量
    auto f1=[=](){
        cout<<x<<y<<z<<endl;
    };//[=]是捕捉所有变量的意思
    f1();

    //以引用的方式捕捉所有的变量
    auto f2=[&](){
        cout<<x<<y<<z<<endl;
    };//[&]是捕捉所有变量的意思
    f2();

    //以值的方式捕捉所有的变量,指定x,y以引用捕捉
    auto f3=[=,&x,&y](){
        cout<<x<<y<<z<<endl;
    };
    f3();

    return 0;
}

lambda的底层其实是一个仿函数

包装器

function

function 是 C++ 标准库中的一个模板类,用于封装可调用对象,包括函数指针、函数对象、lambda 表达式等等,使用时需要functional头文件。

function 的定义如下:

template<class R, class... Args> class function<R(Args...)>;
 

其中 R 是返回类型,Args 是参数类型。通过这个定义,你可以创建一个 function 对象,它可以接受参数为 Args 类型,返回类型为 R 类型的可调用对象。

事例1)

void swap_func(int& r1,int& r2)
{
    int temp;
    temp=r1;
    r1=r2;
    r2=temp;
}


struct swap_2
{
    void operator()(int& r1,int& r2)
    {
        int temp;
        temp=r1;
        r1=r2;
        r2=temp;
    }
};
int main()
{
    int x=119;
    int y=120;
    auto lambdaswap=[](int& r1,int& r2)
    {
        int temp;
        temp=r1;
        r1=r2;
        r2=temp;
    };

    //包装器指向swap_func函数
    function<void(int&,int&)> f1=swap_func;
    f1(x,y);
    cout<<"x:"<<x<<"    y:"<<y<<endl;

    //包装器指向仿函数
    function<void(int&,int&)> f2=swap_2();//swap_2() 是一个函数调用操作符 operator() 被重载的类 swap_2 的匿名对象。在 C++ 中,类的对象也可以被当作函数使用,如果该类定义了一个函数调用操作符 operator(),就可以像调用函数一样使用这个对象。在这种情况下,swap_2() 返回的匿名对象会被当作函数使用,具体来说,它会被当作一个函数对象使用。
    f2(x,y);
    cout<<"x:"<<x<<"    y:"<<y<<endl;

    //包装器指向lambda表达式
    function<void(int&,int&)> f3=lambdaswap;
    f3(x,y);
    cout<<"x:"<<x<<"    y:"<<y<<endl;

    return 0;
}

事例2)

class Test
{
public:
    int add(int x,int y)
    {
        return x+y;
    }
    static int add_s(int x,int y){
        return x+y;
    }
};
int main()
{
    //包装器指向静态成员函数
    //需要加域名
    function<int(int,int)> f1=Test::add_s;
    int sum=f1(1,2);
    cout<<sum<<endl;

    //包装器指向普通成员函数
    //1.需要加域名
    //2.需要取地址
    //3.function需要多加一个类的指针(因为成员函数的参数列表中,隐含一个this指针)
    function<int(Test*,int,int)> f2=&Test::add;
    Test t1;
    int num=f2(&t1,1,2);
    cout<<num<<endl;
}

function封装可调用对象,包括函数指针、函数对象、lambda 表达式时,一定保证参数类型是相同的

bind

在C++中,std::bind 是一个函数模板,用于创建一个可调用对象,该对象可以绑定到函数、成员函数、函数对象或者其他可调用对象,并且可以指定部分或全部参数的值。std::bind 允许你在调用时提供缺少的参数,或者在调用时提供额外的参数。

bind 的基本语法如下:

template< class F, class... Args > 
/*unspecified*/ bind( F&& f, Args&&... args );

其中 F 是可调用对象的类型,args 是可调用对象的参数。bind 返回一个可调用对象,该对象可以通过调用其 operator() 来调用绑定的函数或函数对象,并传递给它们参数。

事例

class Test
{
public:
    int add(int x,int y)
    {
        return x+y;
    }
    static int add_s(int x,int y){
        return x+y;
    }
};

int sub(int x,int y)
{
    return x-y;
}

int main()
{
    //调整参数顺序
    function<int(int,int)> f1=bind(sub,placeholders::_2,placeholders::_1);
    //bind第一个参数是函数名,placeholders::_2,placeholders::_1可用来改变参入参数的顺序的
    int num=f1(2,0);//顺序变为sub(0,2)
    cout<<num<<endl;

    //调整参数个数
    function<int(int)> f2=bind(sub,100,placeholders::_1);
    //我们也可以在绑定的时候,提前加入指定的参数,例如这里的100,这样我们调用sub时就只需要传一个参数
    int num1=f2(1);
    cout<<num1<<endl;

    //调整参数个数
    function<int(int,int)>f3=bind(&Test::add,Test(),placeholders::_1,placeholders::_2);
    //绑定的Test是一个自定义类型的普通成员函数,传函数名时需要加域名和&,这个Test()是Test的匿名对象,需要传递给this指针
    int num2=f3(2,3);
    cout<<num2<<endl;


    return 0;
}

  🌸🌸🌸如果大家还有不懂或者建议都可以发在评论区,我们共同探讨,共同学习,共同进步。谢谢大家! 🌸🌸🌸 

相关推荐

  1. C++11lambda包装(function、bind)

    2024-04-13 13:32:04       14 阅读
  2. C++11lambda表达式 & 包装

    2024-04-13 13:32:04       13 阅读
  3. C++11lambda表达式及function包装

    2024-04-13 13:32:04       6 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-04-13 13:32:04       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-04-13 13:32:04       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-04-13 13:32:04       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-04-13 13:32:04       20 阅读

热门阅读

  1. 学习 Rust 的第二天:Cargo包管理器的使用

    2024-04-13 13:32:04       14 阅读
  2. FineBI概述

    2024-04-13 13:32:04       17 阅读
  3. 前端学习(第三天)

    2024-04-13 13:32:04       53 阅读
  4. 确认网卡绑定的模式

    2024-04-13 13:32:04       20 阅读
  5. C++作业

    2024-04-13 13:32:04       16 阅读