C++11新增特性:lambda表达式、function包装器、bind绑定

C++11 引入了许多强大的新特性,其中 lambda 表达式std::function 包装器std::bind 绑定 是常用且非常有用的功能。下面将详细介绍这三个特性及其使用方法。

1. Lambda 表达式

概述

Lambda 表达式是一种定义匿名函数对象(即闭包)的方法,允许在需要函数的地方直接定义内联的可调用对象。它们简化了回调函数和临时函数对象的使用,使代码更加简洁和易读。

语法

[captures](parameters) -> return_type {
    // function body
};
  • captures:捕获外部变量的方式,可以是值捕获 [=]、引用捕获 [&],或具体指定捕获的变量。
  • parameters:参数列表,与普通函数类似。
  • return_type:返回类型,可以省略,编译器会自动推断。
  • function body:函数体。

示例

#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> numbers = {1, 2, 3, 4, 5};

    // 使用 lambda 表达式打印每个元素
    std::for_each(numbers.begin(), numbers.end(), [](int n) {
        std::cout << n << " ";
    });
    std::cout << std::endl;

    // 使用 lambda 表达式计算总和,捕获外部变量
    int sum = 0;
    std::for_each(numbers.begin(), numbers.end(), [&sum](int n) {
        sum += n;
    });
    std::cout << "Sum: " << sum << std::endl;

    return 0;
}

输出

1 2 3 4 5 
Sum: 15

2. std::function 包装器

概述

std::function 是一个通用的函数包装器,可以存储、复制和调用任何可调用对象(如普通函数、Lambda 表达式、函数对象、绑定表达式等)。它提供了类型擦除的功能,使得可以在运行时灵活地管理不同类型的可调用对象。

头文件

#include <functional>

基本用法

#include <iostream>
#include <functional>

void freeFunction(int n) {
    std::cout << "Free function called with " << n << std::endl;
}

struct Functor {
    void operator()(int n) const {
        std::cout << "Functor called with " << n << std::endl;
    }
};

int main() {
    // 使用 std::function 包装普通函数
    std::function<void(int)> func1 = freeFunction;
    func1(10);

    // 使用 std::function 包装 Lambda 表达式
    std::function<void(int)> func2 = [](int n) {
        std::cout << "Lambda called with " << n << std::endl;
    };
    func2(20);

    // 使用 std::function 包装函数对象
    Functor functor;
    std::function<void(int)> func3 = functor;
    func3(30);

    return 0;
}

输出

Free function called with 10
Lambda called with 20
Functor called with 30

优点

  • 灵活性:可以存储任何类型的可调用对象。
  • 可复制性std::function 对象可以被复制和赋值。
  • 易用性:简化了回调函数的使用,尤其在需要传递多个不同类型的回调时非常有用。

3. std::bind 绑定

概述

std::bind 用于绑定函数的部分参数,生成一个新的可调用对象。它允许预先设定函数的一些参数,从而简化函数调用或适配特定的接口需求。

头文件

#include <functional>

基本用法

#include <iostream>
#include <functional>

int add(int a, int b) {
    return a + b;
}

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

int main() {
    // 绑定 add 函数的第一个参数为 10
    auto add10 = std::bind(add, 10, std::placeholders::_1);
    std::cout << "add10(5): " << add10(5) << std::endl; // 输出 15

    // 绑定 Printer::printSum 的对象和第一个参数为 20
    Printer printer;
    auto print20 = std::bind(&Printer::printSum, &printer, 20, std::placeholders::_1);
    print20(30); // 输出 Sum: 50

    // 与 std::function 结合使用
    std::function<int(int)> func = std::bind(add, 5, std::placeholders::_1);
    std::cout << "func(7): " << func(7) << std::endl; // 输出 12

    return 0;
}

输出

add10(5): 15
Sum: 50
func(7): 12

参数占位符

std::bind 使用占位符(std::placeholders::_1_2,等)来表示绑定后的可调用对象需要的参数位置。这允许在绑定过程中灵活地指定哪些参数被预设,哪些参数由调用时提供。

注意事项

  • 性能:在某些情况下,使用 std::bind 可能不如直接使用 Lambda 表达式高效。现代 C++ 编程中,Lambda 通常更受欢迎。
  • 可读性:过度使用 std::bind 可能会降低代码的可读性,尤其是当绑定的参数较多时。

总结

C++11 的 Lambda 表达式、std::function 包装器和 std::bind 绑定大大增强了 C++ 的函数式编程能力,使代码更加简洁、灵活和易于维护。以下是它们的主要用途:

  • Lambda 表达式:定义内联的匿名函数,适用于需要临时可调用对象的场景,如算法的回调。
  • std::function 包装器:存储和管理各种类型的可调用对象,适用于需要通用回调机制的场景。
  • std::bind 绑定:预设函数参数,适用于需要适配接口或简化函数调用的场景。

在实际开发中,这些特性常常结合使用,以实现更高效和更具表现力的代码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值