C++中的std::function

std::function()是C++标准库中的一个通用多态函数包装器, 它可以存储,复制和调用任意可调用目标(函数,lambda表达式,绑定表达式或其他函数对象).

std::function占用固定尺寸的内存 . 它允许我们将可调用对象(函数,函数指针,Lambda表达式, std::bind以及其他函数对象) 包装成一个对象, 使得我们可以像操作其他对象一样操作和传递可调用对象

std::function是C++引入的标准库和组件,它位于 <functional>头文件中,  它主要作用就是将可调用对象封装成一个函数对象,提供一种统一的方式来处理各种类型的可调用对象

#include <functional>

std::function的基本语法如下

std::function<返回类型(参数类型1,参数类型2,....)>func;

1. 封装函数

复制代码
#include <iostream>
#include <functional>

void greet()
{
   std::cout << "Hello, Beijing!" << std::end1;
}

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 function test!" << std::end1;
      };

      func(); //调用封装的lambda表达式
     return 0;
}
复制代码

 

3. 封装可调用对象 (仿函数)

复制代码
#include <iostream>
#include <functional>

class Greet
{
    public:
        void operator()() const{
            std::cout << "functor test!" << std::end1;
        }
};

int main()
{
     std::function<void()> func = Greet();
     func(); //调用封装的仿函数
     return 0;
}
复制代码

 

4. 类的成员函数和类的静态函数

复制代码
Class MyClass
{
    public:
        //类的成员函数
        int MyClassMember(int x)  {return x;}

        //类的静态函数
        static int MyStaticMember(int y)  {return y;}
}


int main()
{
     //类的成员函数,需要先bind到具体的类
     MyClass myObj;
     
     std::function<int(int)> func = std::bind(&myObj::MyClassMember,myObj,std::placeholders::_1);  //_1表示占位符,调用时传参数
   int result = func(10);

   
   //类的静态函数,可以认为是普通函数,和调用普通函数一样
   func = MyClass::MyStaticMember;
   result = func(50);

   return 0;
  

}
复制代码

 

 

看完上面这几个例子,我们来了解一下std::function的实现原理

 std::function通常使用类型擦除和小对象优化(Small Object Optimization, SOO) 来实现

 类型擦除

std::function使用类型擦除来存储不同类型的可调用对象,这意味着它通过一个固定大小的存储空间和一个指向这些对象的虚表(vtable)来实现多态性

类型擦除允许std::function在运行时处理各种不同的类型,而不需要知道这些类型的细节

小对象优化

对于小对象(通常是指尺寸较小可以直接存储在std::function内部的对象), std::function会直接在它内部存储这些对象. 这就避免了动态内存分配的开销

对于大对象(超出 std::function内部存储容量的对象), std::function会在堆上分配内存,同时在std::function内部存储一个指向这些对象的指针

std::function总是占有固定尺寸的内存, 它的内部通常包含以下几个部分:

  • 一个指向实际存储对象的指针和存储小对象的内部缓冲区
  • 一个指向虚表的指针,用于多态调用
  • 一些额外的元数据,用于管理存储和调用

所以,不管存储对象多大或者多小,std::function的实例总是占用固定大小的内存,以包含这些指针和元数据

 

总之,std::function对象是对C++中现有的可调用实体的一种类型安全的包裹(我们知道像函数指针这类可调用实体,是类型不安全的). 用std::function来实现回调函数,在函数形参中代替函数指针,更安全也更可视化

 

posted on   新西兰程序员  阅读(827)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
历史上的今天:
2023-12-02 [LeetCode-双指针-中等] 盛最多水的容器
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

点击右上角即可分享
微信分享提示