C++11新特性—std:function模板类

37 篇文章 0 订阅
26 篇文章 0 订阅

std::function模板类

1.定义

std::function 是 C++11 引入的一个模板类,位于 <functional> 头文件中。它是一个通用的可调用对象包装器(function object wrapper),能够存储、复制和调用任何可以调用的目标(Callable target),这些目标包括普通函数、Lambda 表达式、函数对象(仿函数)、绑定表达式(通过 std::bind 创建的)以及其他函数对象等。

2.特点

std::function 的主要特点包括:

  1. 类型擦除std::function 通过类型擦除技术,允许你存储和调用不同类型的可调用实体,而无需关心它们的确切类型。这使得 std::function 在需要存储或传递可调用实体的泛型编程和回调函数中非常有用。
  2. 灵活性:你可以将任何可调用实体赋值给 std::function 对象,只要该实体的调用签名与 std::function 的模板参数指定的签名兼容。
  3. 易用性std::function 提供了类似于普通函数的调用语法,使得调用存储的可调用实体变得简单直观。
  4. 性能开销:虽然 std::function 提供了很大的灵活性,但它也可能引入一些性能开销,因为它需要动态地处理不同类型的可调用实体。在性能敏感的代码中,直接使用函数指针、Lambda 表达式或函数对象可能更为高效。

使用 std::function 时,你需要指定一个函数签名作为模板参数,这个签名描述了被包装的可调用实体应该具有的形式(即返回类型和参数类型)。然后,你可以将任何与该签名兼容的可调用实体赋值给 std::function 对象,并通过该对象调用它。

3.案例演示

#include <iostream>  
#include <functional>  
  
// 一个简单的函数  
int add(int x, int y) {  
    return x + y;  
}  
  
int main() {  
    // 创建一个 std::function 对象,它可以存储任何接受两个 int 参数并返回 int 的可调用实体  
    std::function<int(int, int)> func;  
  
    // 将函数赋值给 std::function 对象  
    func = add;  
  
    // 调用存储的函数  
    std::cout << "5 + 3 = " << func(5, 3) << std::endl;  
  
    // 也可以将 Lambda 表达式赋值给 std::function 对象  
    func = [](int x, int y) { return x * y; };  
  
    // 调用存储的 Lambda 表达式  
    std::cout << "5 * 3 = " << func(5, 3) << std::endl;  
  
    return 0;  
}

在这个示例中,我们首先创建了一个 std::function<int(int, int)> 类型的对象 func,它可以存储任何接受两个 int 参数并返回 int 的可调用实体。然后,我们将一个函数 add 和一个 Lambda 表达式分别赋值给 func,并通过 func 调用了它们。

4.<functional> 标准库

4.1概述

<functional> 是 C++ 标准库中的一个头文件,它提供了对函数对象(也称为仿函数或函子)和可调用实体的支持。这些功能主要用于泛型编程中,特别是在与算法(如 <algorithm> 中定义的那些)和标准容器(如 <vector><list> 等)的交互中。<functional> 头文件定义了几个模板类和函数,这些模板类和函数可以帮助你创建和使用可调用实体。

4.2主要组件

  • 函数对象(Functors):任何可以像函数那样被调用的对象都可以被视为函数对象。它们通常通过重载 operator() 来实现调用操作。<functional> 提供了一些预定义的函数对象模板,如 std::plusstd::minusstd::multipliesstd::divides 等,用于执行基本的算术运算。
  • 绑定器(Binders)<functional> 中的 std::bind 函数可以用来创建一个新的可调用实体,这个实体会将某些固定的参数绑定到另一个可调用实体上。这在你需要部分应用函数时非常有用,即你有一个函数需要多个参数,但你只想现在提供其中的一些参数,而稍后提供其他参数。
  • 函数包装器(Function Wrappers)std::function 是一个通用的可调用对象包装器,它可以保存、复制和调用任何可调用目标(函数、Lambda 表达式、绑定表达式、函数对象等)。它提供了一种类型安全的、通用的方式来存储和调用回调函数。
  • 内存和比较函数对象<functional> 还提供了一些用于内存和比较的函数对象,如 std::mem_fn 用于生成指向成员函数的指针的包装器,以及 std::lessstd::greater 等用于比较操作的函数对象。

4.3案例测试

以下是一个使用 <functional> 中组件的示例:

#include <iostream>  
#include <functional>  
#include <vector>  
#include <algorithm>  
  
int main() {  
    std::vector<int> numbers = {1, 2, 3, 4, 5};  
  
    // 使用 std::plus 和 std::for_each  
    std::for_each(numbers.begin(), numbers.end(), std::bind(std::plus<int>(), std::placeholders::_1, 10));  
  
    // 注意:上面的 std::bind 调用实际上不会改变 numbers 中的值,因为 std::for_each 并不捕获返回值。  
    // 更好的做法是使用 lambda 表达式。  
  
    // 使用 lambda 表达式和 std::for_each  
    std::for_each(numbers.begin(), numbers.end(), [](int& n) { n += 10; });  
  
    // 输出修改后的 numbers  
    for (int n : numbers) {  
        std::cout << n << ' ';  
    }  
  
    // 使用 std::function  
    std::function<void(int)> print = [](int i) { std::cout << i << ' '; };  
    std::for_each(numbers.begin(), numbers.end(), print);  
  
    return 0;  
}

请注意,示例中的 std::bind 用法并不适合直接修改容器中的元素,因为 std::for_each 默认不捕获返回值。这里仅用于演示 std::bind 的基本用法。在实际应用中,对于需要修改容器元素的场景,Lambda 表达式通常是更好的选择。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值