C++ 11新特性— lambda表达式、std::function、std::bind

文摘   2024-07-10 11:14   上海  

前言

本文参考整理一下C++11中三个比较重要的新特性:lambda表达式、std::function、std::bind。本文学习整理来源于其他优秀博客,如有侵权请联系我。

一、lambda表达式

lambda表达式又称为匿名表达式,是C11提出的新语法。
lambda表达式定义了一个匿名函数,并且可以捕获一定范围内的变量。语法形式如下:

[ capture ] ( params ) opt -> ret { body; };

capture:捕获列表
params:参数列表
opt:函数选项
ret:返回值类型
body:函数体

2.1 使用案例

==================================
// 1  匿名调用
    [](string name)
    {
        cout << "this is anonymous" << endl;
        cout << "hello " << name << endl;
    }("zack");
==================================    
 // 2 通过auto赋值
    auto fname = [](string name)
    {
        cout << "this is auto  " << endl;
        cout << "hello " << name << endl;
    };

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

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

    funcName("Uncle Wang"); 

2.2 捕获案例

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");

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");

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;
   }();

二 std::function

C++中的std::function是一个强大而灵活的工具,它允许我们将可调用对象(函数、函数指针、Lambda表达式等)包装成一个对象,使得我们可以像操作其他对象一样操作和传递可调用对象。

std::function 是C++11引入的标准库组件,位于头文件中。

2.1 使用案例

1 封装函数指针

#include <iostream>
#include <functional>

void greet() {
    std::cout << "Hello, World!" << std::endl;
}

int main() {
    std::function<void()> func = greet;
    func();  // 调用封装的函数指针
    return 0;
}

2 封装Lambda表达式

#include <iostream>
#include <functional>

int main() {
    std::function<void()> func = []() {
    std::cout << "Lambda says hi!" << std::endl;
    };
    func();  // 调用封装的Lambda表达式
    return 0;
}

3 封装可调用对象

#include <iostream>
#include <functional>

class Greeter {
public:
    void operator()() const {
        std::cout << "Class Greeter says hello!" << std::endl;
    }
};

int main() {
    std::function<void()> func = Greeter();
    func();  // 调用封装的可调用对象
    return 0;
}

4 可变参数

#include <iostream>
#include <functional>

void printSum(int a, int b) {
    std::cout << "Sum: " << a + b << std::endl;
}

int main() {
    std::function<void(int, int)> func = printSum;
    func(3, 4);  // 输出 Sum: 7
    return 0;
}

三、std::bind

std::bind 是 C++11 标准库中的一个函数模板,用于创建一个可调用对象(函数对象或函数指针),并绑定到指定的参数。它可以用于延迟函数调用、部分应用函数、改变函数参数顺序等场景。

下面是 std::bind 的主要特点和用法:

延迟函数调用:std::bind 允许我们在创建可调用对象时不立即调用函数,而是将函数对象和参数绑定起来,以便在稍后的时间点进行调用。
部分应用函数:std::bind 允许我们在创建可调用对象时只绑定部分参数,剩余的参数可以在稍后的调用中提供,从而实现函数的部分应用。
改变函数参数顺序:std::bind 允许我们改变函数的参数顺序,即将函数的某些参数按照指定的顺序重新排列。
支持占位符: std::bind 支持占位符(std::placeholders::_1、std::placeholders::_2 等),用于指示在调用时提供的参数的位置。

基本用法

#include <iostream>
#include <functional>

// 函数对象类
class MyFunctionObject {
public:
    int operator()(int a, int b, int c) const {
        return a + b + c;
    }
};

int main() {
    MyFunctionObject myObject;

    // 绑定函数对象和参数
    auto func1 = std::bind(myObject, 1, 2, 3);

    // 部分应用函数
    auto func2 = std::bind(myObject, std::placeholders::_1, 2, std::placeholders::_2);

    std::cout << "Result 1: " << func1() << std::endl; // 输出:6
    std::cout << "Result 2: " << func2(10, 20) << std::endl; // 输出:32

    return 0;
}

在这个示例中,我们使用 std::bind 将函数对象 myObject 绑定到参数,并创建了两个可调用对象 func1 和 func2。func1 绑定了完整的参数,而 func2 则只绑定了部分参数,剩余的参数在调用时提供。

std::function 与 std::bind 一起使用

案例

#include <iostream>
#include <functional>

void printMessage(const std::string& message, int value) {
    std::cout << message << ": " << value << std::endl;
}

int main() {
    auto printHello = std::bind(printMessage, "Hello", std::placeholders::_1);
    std::function<void(int)> func = printHello;
    func(42);  // 输出 Hello: 42
    return 0;
}

参考文章

https://gitbookcpp.llfc.club/sections/cpp/section7/cpp34.html 

https://cloud.tencent.com/developer/article/2388825

https://cloud.tencent.com/developer/article/2409110


欢迎关注公众号:DBA札记,一起交流数据库技术。欢迎觉得读完本文有收获,可以转发给其他朋友,大家一起学习进步!谢谢大家。

DBA札记
dba 数据库 知识科普 踩坑指南 经验分享 原理解读
 最新文章