服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C/C++ - C++11 std::function和std::bind 的使用示例详解

C++11 std::function和std::bind 的使用示例详解

2023-03-19 15:52泡沫o0 C/C++

C++11中的std::function和std::bind是函数对象的重要组成部分,它们可以用于将函数和参数绑定在一起,形成一个可调用的对象,这篇文章主要介绍了C++11 std::function和std::bind 的使用示例详解,需要的朋友可以参考下

概述

C++11中的std::functionstd::bind是函数对象的重要组成部分,它们可以用于将函数和参数绑定在一起,形成一个可调用的对象。
std::function可以存储任意可调用对象,包括函数指针、函数对象、lambda表达式等,而std::bind则可以将函数和参数绑定在一起,形成一个新的可调用对象。它们的使用可以大大简化代码,提高代码的可读性和可维护性。

可调用对象

C++中有如下几种可调用对象,函数、函数指针、lambda表达式、bind对象、函数对象
其中,lambda表达式和bind对象是C++11标准中提出的(bind机制并不是新标准中首次提出,而是对旧版本中bind1st和bind2st的合并)。

std::function

std::function是一个可调用对象包装器,是一个类模板,可以容纳除了类成员函数指针之外的所有可调用对象,它可以用统一的方式处理函数、函数对象、函数指针,并允许保存和延迟它们的执行。
使用std::function可以实现回调函数、事件处理等功能。

std::function函数原型

?
1
2
3
4
5
#include <functional>
template<class R, class... Args>
class function<R(Args...)>;
//其中,R 表示返回值类型,Args... 表示参数类型列表。
//例如,function<int(float, double)> 表示一个返回值为 int,接受一个 float 和一个 double 类型参数的函数对象。

std::function的主要作用

  • 对C++中各种可调用实体(普通函数、Lambda表达式、函数指针、以及其它函数对象等)的封装,形成一个新的可调用的std::function对象,简化调用;
  • 对C++中现有的可调用实体的一种类型安全的包裹(如:函数指针这类可调用实体,是类型不安全的)。
  • 将函数作为参数传递给其他函数;
  • 将函数作为返回值返回;
  • 将函数对象作为参数传递给其他函数;
  • 将函数对象作为返回值返回。
?
1
2
3
4
5
6
7
8
9
10
//例如,定义一个返回值为int,参数为两个int的函数对象:
std::function<int(int, int)>func;
 
//可以将一个函数指针或lambda表达式赋值给函数对象:
int add(int a, int b) { return a +b; }
func = add; // 函数指针赋值
func = [](int a, int b) { return a + b; };// lambda表达式赋值
 
//调用函数对象可以使用operator(),例如:
int result = func(1, 2); // 调用add函数,返回3

std::function的优缺点

  • 优点:

可以方便地实现回调函数、事件处理等功能,同时也可以用于实现函数对象的封装和传递。

  • 缺点:

它的使用会带来一定的性能开销,因为它需要在运行时进行类型检查和动态分配内存。
此外,如果使用不当,也容易引起内存泄漏和对象生命周期管理的问题。

std::bind

std::function是一个可调用对象包装器,是一个类模板,可以容纳除了类成员函数指针之外的所有可调用对象,它可以用统一的方式处理函数、函数对象、函数指针,并允许保存和延迟它们的执行。

std::bind函数原型

?
1
2
3
template<class F, class... Args>
/unspecified/ bind(F&& f, Args&&... args);
//其中,F是要绑定的函数对象,Args是要绑定的参数。返回值是一个新的可调用对象,可以直接调用或者存储起来后再调用。

std::bind的主要作用

  • 将可调用对象和其参数绑定成一个仿函数;
  • 只绑定部分参数,减少可调用对象传入的参数。
  • 绑定函数对象的参数,生成一个新的可调用对象,可以方便地将函数对象作为参数传递给其它函数。
  • 可以将成员函数绑定到对象上,生成一个新的可调用对象,方便地调用成员函数。
  • 可以将成员函数绑定到对象指针上,生成一个新的可调用对象,方便地调用成员函数。
  • 可以将成员函数绑定到对象引用上,生成一个新的可调用对象,方便地调用成员函数。
  • 可以将函数对象绑定到函数指针上,生成一个新的可调用对象,方便地调用函数对象。
  • 可以将函数对象绑定到函数引用上,生成一个新的可调用对象,方便地调用函数对象。
  • 可以将函数对象绑定到std::function对象上,生成一个新的可调用对象,方便地调用函数对象。

例如,我们有一个函数对象:
void foo(int a, int b, int c) { std::cout << a << " " << b << " " << c << std::endl; }
我们可以使用std::bind将它绑定到一些参数上:
auto f = std::bind(foo, 1, 2, 3);
这里,f是一个新的可调用对象,它绑定了foo函数和参数1、2、3。我们可以像调用原始函数对象一样调用它:
f(); // 输出:1 2 3
我们也可以只绑定部分参数:
auto g = std::bind(foo, 1, std::placeholders::_1, 3);
这里,std::placeholders::_1表示占位符,它表示在调用g时,第二个参数会被传递给foo函数。我们可以这样调用g:
g(2); // 输出:1 2 3
这就是std::bind的基本用法。它可以方便地将函数对象和参数绑定在一起,生成一个新的可调用对象。

std::bind的优缺点

优点:

可以方便地实现函数对象的复用和参数的延迟绑定,从而提高代码的可读性和可维护性。

缺点:

可能会导致代码的复杂性增加,特别是当参数较多时,需要谨慎使用。

代码示例

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#pragma once
 
#include <iostream>
#include <functional>
class A {
public:
 bool TESTA(int, char*, int) { /* implementation */ }
};
 
class B {
public:
 bool TESTB(std::function<bool(int, char*, int)> func) { /* implementation */ }
};
 
int main() {
 A objA;
 B objB;
 auto lambda = [](int a, char* b, int c) { /* implementation */ };
 objB.TESTB(lambda);
 objB.TESTB(std::bind(&A::TESTA, &objA, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
 return 0;
}

总结

  • 预绑定的参数是以值传递的形式,不预绑定的参数要用std::placeholders(占位符)的形式占位,从_1开始,依次递增,是以引用传递的形式;
  • std::placeholders表示新的可调用对象的第几个参数,而且与原函数的该占位符所在位置的进行匹配;
  • bind绑定类成员函数时,第一个参数表示对象的成员函数的指针,第二个参数表示对象的地址,这是因为对象的成员函数需要有this指针。并且编译器不会将对象的成员函数隐式转换成函数指针,需要通过&手动转换;
  • std::bind的返回值是可调用实体,可以直接赋给std::function。

到此这篇关于C++11 std::function和std::bind 的使用的文章就介绍到这了,更多相关C++11 std::function和std::bind内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.csdn.net/qq_21438461/article/details/129581132

延伸 · 阅读

精彩推荐
  • C/C++C++设计模式之备忘录模式

    C++设计模式之备忘录模式

    这篇文章主要介绍了C++设计模式之备忘录模式,本文讲解了什么是备忘录模式、备忘录模式的UML类图、备忘录模式的使用场合等内容,需要的朋友可以参考下...

    果冻想10762021-02-05
  • C/C++Linux中使用VS Code编译调试C++项目详解

    Linux中使用VS Code编译调试C++项目详解

    最近因为项目的需求,需要在Linux下开发C++相关项目,经过一番摸索最终实现了,下面这篇文章就给大家简单总结了一下如何通过VS Code进行编译调试的一些...

    DoubleLi12862021-04-21
  • C/C++c++先序二叉树的构建详解

    c++先序二叉树的构建详解

    在本篇文章里小编给大家分享了关于c++先序二叉树的构建的相关知识点,需要的朋友们跟着学下。 ...

    C++教程网3842021-07-28
  • C/C++C++课程设计之运动会管理系统

    C++课程设计之运动会管理系统

    这篇文章主要为大家详细介绍了C++课程设计之运动会管理系统,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    自动化1123班潘国成10642021-07-02
  • C/C++C语言数据结构二叉树简单应用

    C语言数据结构二叉树简单应用

    这篇文章主要介绍了C语言数据结构二叉树简单应用的相关资料,需要的朋友可以参考下...

    super_yc6682021-05-12
  • C/C++C++运算符重载的详细讲解

    C++运算符重载的详细讲解

    这篇文章主要给大家介绍了关于C++运算符重载的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋...

    Thrush''''s note5412021-10-29
  • C/C++VisualStudio2019配置OpenCV4.5.0的方法示例

    VisualStudio2019配置OpenCV4.5.0的方法示例

    这篇文章主要介绍了VisualStudio2019配置OpenCV4.5.0的方法示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋...

    点云侠11132021-10-28
  • C/C++C语言代码实现简单扫雷游戏

    C语言代码实现简单扫雷游戏

    这篇文章主要为大家详细介绍了C语言代码实现简单扫雷游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    菜菜是真菜4202021-10-21