C++面试基础系列-函数指针与指针函数

2024-08-25 00:36

本文主要是介绍C++面试基础系列-函数指针与指针函数,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

系列文章目录


文章目录

  • 系列文章目录
  • C++面试基础系列-函数指针与指针函数
    • Overview
    • 1.function_pointer函数指针
    • 2.pointer_function指针函数
    • 3.面试中,最喜欢的是函数指针和指针函数的区别
      • 3.1.定义
      • 3.2.用法
      • 3.3.存储方式
    • 4.函数指针用法
    • 5.指针函数
      • 5.1.动态内存分配
      • 5.2.返回复杂数据结构的指针
      • 5.3.作为函数参数传递
    • 关于作者


C++面试基础系列-函数指针与指针函数

Overview

1.function_pointer函数指针

  • function_pointer函数指针也是一个指针,
    • 只不过函数指针可以指向函数,可以通过该指针调用函数
    • 联想到重载,多态,模板,只不过函数指针需要重新调整指针指向的函数类型

2.pointer_function指针函数

  • 指针函数实际上只是函数返回值返回一个指针

3.面试中,最喜欢的是函数指针和指针函数的区别

函数指针和指针函数是两个不同的概念,主要区别如下:

3.1.定义

  1. 指针函数:
    • 本质是一个函数,其返回值是一个指针。
    • 例如:int* fun() { /* 函数体 */ },这里的函数 fun就是一个指针函数,它返回一个指向整数的指针。
  2. 函数指针:
    • 是指向函数的指针变量。
    • 例如:int (*pf)();,这里 pf是一个函数指针,它指向一个返回值为整数的函数。

3.2.用法

  1. 指针函数的用法:

    • 先调用指针函数,得到一个指针结果,然后通过这个指针访问其所指向的内存空间中的数据。

    • 例如:

    • 看出下面代码的错误了吗?

      int* fun() {int a = 10;return &a;
      }
      int main() {int* ptr = fun();printf("%d\n", *ptr);//errorreturn 0;
      }
      
    • ERROR:a是一个局部变量,调用指向a的指针,会出现内存泄漏,应避免这种用法。

  2. 函数指针的用法:

    • 可以将函数指针作为参数传递给其他函数,实现回调函数的功能。

    • 例如:

      void callback(int (*func)(int), int arg) {int result = func(arg);printf("Result: %d\n", result);
      }
      int square(int num) {return num * num;
      }
      int main() {callback(square, 5);return 0;
      }
      

3.3.存储方式

  1. 指针函数:在内存中与普通函数一样,有特定的代码段存储函数体,执行时将在该代码段中运行。返回的指针则存储在相应的内存地址中。
  2. 函数指针:本身作为一个变量存储在内存中,它的值是所指向函数的入口地址。

4.函数指针用法

函数指针是C++中一种重要的特性,它允许将函数作为值来处理。以下是函数指针的一些常见用法:

  1. 动态函数调用
    使用函数指针可以在运行时决定调用哪个函数。这在实现回调机制、策略模式或事件处理系统时非常有用。

    void function1() { std::cout << "Function 1" << std::endl; }
    void function2() { std::cout << "Function 2" << std::endl; }
    void (*functionPtr)() = function1; // 函数指针指向function1
    functionPtr(); // 调用function1
    functionPtr = function2; // 现在指向function2
    functionPtr(); // 调用function2
    
  2. 实现回调函数
    函数指针经常用于回调函数,即作为参数传递给另一个函数,然后在该函数内部调用。

    void callback(void (*func)()) {func();
    }
    void myFunction() {std::cout << "Hello from myFunction" << std::endl;
    }
    int main() {callback(myFunction);
    }
    
  3. 作为数据成员
    在类中使用函数指针作为数据成员,允许对象根据行为的不同来调用不同的函数。

    class Event {
    public:void (*handler)(); // 函数指针作为数据成员
    };
    Event event;
    event.handler = myFunction;
    event.handler(); // 调用myFunction
    
  4. 数组和向量
    函数指针可以存储在数组或向量中,用于管理一组函数。

    void (*functions[])() = {function1, function2};
    for (auto func : functions) {func();
    }
    
  5. 函数指针类型转换
    在某些情况下,可能需要将一个函数指针转换为另一个类型的指针,或者反之。

    typedef void (*FuncType)();
    int (*intFunc)(int) = static_cast<int (*)(int)>(function1); // 类型转换
    
  6. 实现多态
    函数指针可以用来实现类似多态的行为,尤其是在使用函数作为类的成员或参数时。

    class Base {
    public:virtual void execute() = 0;
    };
    class Derived : public Base {
    public:void execute() override {std::cout << "Execute in Derived" << std::endl;}
    };
    Base* basePtr = new Derived();
    (*basePtr).execute(); // 多态调用
    delete basePtr;
    
  7. 用于排序和搜索算法
    在标准库算法中,如 std::sortstd::find_if,可以传递函数指针或函数对象来指定自定义的比较或谓词函数。

    int array[] = {5, 3, 2, 4, 1};
    std::sort(std::begin(array), std::end(array),[](int a, int b) { return a > b; }); // lambda表达式作为函数指针使用
    
  8. 信号处理
    在Unix和类Unix系统中,signal函数允许为各种信号注册信号处理函数,这通常通过函数指针完成。

    void signalHandler(int signal) {std::cout << "Signal received" << std::endl;
    }
    // 注册信号处理函数
    signal(SIGINT, signalHandler);
    
  9. 函数指针的指针
    可以创建函数指针的数组或指针,这在实现函数表或多级回调时很有用。

    void (*functionTable[])() = {function1, function2};
    void (**functionTablePtr)() = functionTable;
    (*functionTablePtr)[0](); // 调用function1
    
  10. 与C ABI兼容
    由于C++兼容C的ABI(应用程序二进制接口),函数指针在C和C++之间可以互用,这在编写跨语言的库或接口时非常有用。

函数指针是C++中实现多态、回调和高阶函数(即接受或返回函数的函数)的关键工具。然而,过度使用函数指针可能会使代码难以理解和维护,因此应谨慎使用,并考虑使用更现代的C++特性,如函数对象、lambda表达式和std::function。

5.指针函数

指针函数是一种返回指针类型的函数。以下是指针函数的一些用法:

5.1.动态内存分配

在 C 和 C++中,可以使用指针函数来动态分配内存并返回指向该内存的指针。例如:

int* allocateArray(int size) {int* arr = new int[size];return arr;
}

在这个例子中,allocateArray函数接受一个整数参数size,用于指定要分配的数组大小。函数内部使用new关键字动态分配一个整数数组,并返回指向该数组的指针。使用时可以这样调用:

int main() {int* myArray = allocateArray(10);// 使用 myArraydelete[] myArray;return 0;
}

5.2.返回复杂数据结构的指针

当需要从函数中返回一个复杂的数据结构时,可以使用指针函数。例如,假设有一个结构体表示学生信息:

struct Student {std::string name;int age;
};Student* createStudent(std::string name, int age) {Student* s = new Student;s->name = name;s->age = age;return s;
}

使用方式如下:

int main() {Student* student = createStudent("Tom", 18);// 使用 studentdelete student;return 0;
}

5.3.作为函数参数传递

指针函数的返回值可以作为其他函数的参数进行传递。例如:

void processArray(int* arr, int size) {for (int i = 0; i < size; i++) {arr[i] *= 2;}
}int* generateArray(int size) {int* arr = new int[size];for (int i = 0; i < size; i++) {arr[i] = i + 1;}return arr;
}

可以这样调用:

int main() {int* myArray = generateArray(5);processArray(myArray, 5);// 使用 myArraydelete[] myArray;return 0;
}

在这个例子中,generateArray函数生成一个整数数组,然后将其作为参数传递给processArray函数进行处理。


关于作者

  • 微信公众号:WeSiGJ
  • GitHub:https://github.com/wesigj/cplusplusboys
  • CSDN:https://blog.csdn.net/wesigj
  • 微博:
  • -版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

这篇关于C++面试基础系列-函数指针与指针函数的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1104052

相关文章

C++统计函数执行时间的最佳实践

《C++统计函数执行时间的最佳实践》在软件开发过程中,性能分析是优化程序的重要环节,了解函数的执行时间分布对于识别性能瓶颈至关重要,本文将分享一个C++函数执行时间统计工具,希望对大家有所帮助... 目录前言工具特性核心设计1. 数据结构设计2. 单例模式管理器3. RAII自动计时使用方法基本用法高级用法

从基础到高级详解Python数值格式化输出的完全指南

《从基础到高级详解Python数值格式化输出的完全指南》在数据分析、金融计算和科学报告领域,数值格式化是提升可读性和专业性的关键技术,本文将深入解析Python中数值格式化输出的相关方法,感兴趣的小伙... 目录引言:数值格式化的核心价值一、基础格式化方法1.1 三种核心格式化方式对比1.2 基础格式化示例

redis-sentinel基础概念及部署流程

《redis-sentinel基础概念及部署流程》RedisSentinel是Redis的高可用解决方案,通过监控主从节点、自动故障转移、通知机制及配置提供,实现集群故障恢复与服务持续可用,核心组件包... 目录一. 引言二. 核心功能三. 核心组件四. 故障转移流程五. 服务部署六. sentinel部署

GO语言中函数命名返回值的使用

《GO语言中函数命名返回值的使用》在Go语言中,函数可以为其返回值指定名称,这被称为命名返回值或命名返回参数,这种特性可以使代码更清晰,特别是在返回多个值时,感兴趣的可以了解一下... 目录基本语法函数命名返回特点代码示例命名特点基本语法func functionName(parameters) (nam

深入解析C++ 中std::map内存管理

《深入解析C++中std::map内存管理》文章详解C++std::map内存管理,指出clear()仅删除元素可能不释放底层内存,建议用swap()与空map交换以彻底释放,针对指针类型需手动de... 目录1️、基本清空std::map2️、使用 swap 彻底释放内存3️、map 中存储指针类型的对象

Python Counter 函数使用案例

《PythonCounter函数使用案例》Counter是collections模块中的一个类,专门用于对可迭代对象中的元素进行计数,接下来通过本文给大家介绍PythonCounter函数使用案例... 目录一、Counter函数概述二、基本使用案例(一)列表元素计数(二)字符串字符计数(三)元组计数三、C

从基础到进阶详解Python条件判断的实用指南

《从基础到进阶详解Python条件判断的实用指南》本文将通过15个实战案例,带你大家掌握条件判断的核心技巧,并从基础语法到高级应用一网打尽,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一... 目录​引言:条件判断为何如此重要一、基础语法:三行代码构建决策系统二、多条件分支:elif的魔法三、

Python WebSockets 库从基础到实战使用举例

《PythonWebSockets库从基础到实战使用举例》WebSocket是一种全双工、持久化的网络通信协议,适用于需要低延迟的应用,如实时聊天、股票行情推送、在线协作、多人游戏等,本文给大家介... 目录1. 引言2. 为什么使用 WebSocket?3. 安装 WebSockets 库4. 使用 We

C++ STL-string类底层实现过程

《C++STL-string类底层实现过程》本文实现了一个简易的string类,涵盖动态数组存储、深拷贝机制、迭代器支持、容量调整、字符串修改、运算符重载等功能,模拟标准string核心特性,重点强... 目录实现框架一、默认成员函数1.默认构造函数2.构造函数3.拷贝构造函数(重点)4.赋值运算符重载函数

Python中的filter() 函数的工作原理及应用技巧

《Python中的filter()函数的工作原理及应用技巧》Python的filter()函数用于筛选序列元素,返回迭代器,适合函数式编程,相比列表推导式,内存更优,尤其适用于大数据集,结合lamb... 目录前言一、基本概念基本语法二、使用方式1. 使用 lambda 函数2. 使用普通函数3. 使用 N