自学内容网 自学内容网

细究C/C++函数指针

函数指针

在 C++ 中,函数指针是指向函数的指针。函数指针允许您动态调用函数、传递函数作为参数,或者存储函数的地址。

1. 函数指针的声明

函数指针的声明需要指定函数的返回类型和参数类型。基本语法如下:

返回类型 (*指针名)(参数类型1, 参数类型2, ...);

示例:
假设有一个返回 int 类型、接受两个 int 类型参数的函数指针:

int (*funcPtr)(int, int);

2. 指向函数的指针赋值

可以将函数的地址赋值给函数指针。注意:在赋值时不需要使用取地址符 &,因为函数名本身就是一个指向函数的指针。

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

int (*funcPtr)(int, int) = add;  // 将 add 的地址赋给 funcPtr

3. 使用函数指针调用函数

通过函数指针调用函数的语法如下:

int result = (*funcPtr)(arg1, arg2);

或者,您也可以直接使用函数指针名:

int result = funcPtr(arg1, arg2);

示例代码

#include <iostream>

// 函数定义
int add(int a, int b) {
    return a + b;
}

int subtract(int a, int b) {
    return a - b;
}

int main() {
    // 声明函数指针
    int (*funcPtr)(int, int);

    // 将指针指向 add 函数
    funcPtr = add;

    // 调用 add 函数
    std::cout << "Add: " << funcPtr(3, 5) << std::endl;  // 输出 8

    // 将指针指向 subtract 函数
    funcPtr = subtract;

    // 调用 subtract 函数
    std::cout << "Subtract: " << funcPtr(10, 4) << std::endl;  // 输出 6

    return 0;
}

4. 将函数指针作为参数传递

您可以将函数指针作为参数传递给另一个函数。以下是一个简单示例:

#include <iostream>

// 函数定义
int add(int a, int b) {
    return a + b;
}

// 接受函数指针作为参数的函数
void performOperation(int (*operation)(int, int), int x, int y) {
    std::cout << "Result: " << operation(x, y) << std::endl;
}

int main() {
    // 传递函数指针
    performOperation(add, 5, 7);  // 输出 Result: 12
    return 0;
}

5. 函数指针数组

您可以创建一个函数指针数组,用于存储多个函数的地址。例如:

#include <iostream>

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

int subtract(int a, int b) {
    return a - b;
}

int multiply(int a, int b) {
    return a * b;
}

int main() {
    // 创建一个函数指针数组
    int (*operations[3])(int, int) = { add, subtract, multiply };

    int x = 6, y = 3;

    for (int i = 0; i < 3; ++i) {
        std::cout << "Result: " << operations[i](x, y) << std::endl;
    }

    return 0;
}

函数指针必须与函数的签名(返回类型和参数类型)完全匹配。
使用函数指针时,要确保所指向的函数在调用时是有效的,以避免运行时错误。

std::function与函数指针

1. std::function 的基本概念

std::function 是 C++11 引入的一个通用、类型安全的可调用对象封装器。它可以存储任何可以调用的目标,包括:

  • 普通函数
  • 函数指针
  • Lambda 表达式
  • 绑定的函数对象(使用 std::bind
  • 实现了 operator() 的对象(函数对象)

基本语法

#include <functional>

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

2. 与函数指针的对比

特性函数指针std::function
类型只能指向特定类型的函数可以存储多种类型的可调用对象
类型安全类型不安全类型安全
灵活性只能指向函数可以指向 Lambda、函数对象等
内存管理需要手动管理自动管理
可用于泛型不易与模板结合易于与模板结合

3. std::function 的详细用法

3.1. 使用普通函数

#include <iostream>
#include <functional>

// 普通函数
int add(int a, int b) {
    return a + b;
}

int main() {
    // 创建 std::function 对象
    std::function<int(int, int)> func = add;

    // 调用函数
    std::cout << "Add: " << func(3, 5) << std::endl;  // 输出 8

    return 0;
}

3.2. 使用 Lambda 表达式

Lambda 表达式是 std::function 的一种常见用法:

#include <iostream>
#include <functional>

int main() {
    // 使用 Lambda 表达式
    std::function<int(int, int)> func = [](int a, int b) { return a + b; };

    std::cout << "Add: " << func(3, 5) << std::endl;  // 输出 8

    return 0;
}

3.3. 使用 std::bind 绑定参数

std::bind 允许您创建一个新函数,其中一些参数已经绑定到特定值:

#include <iostream>
#include <functional>

int multiply(int a, int b) {
    return a * b;
}

int main() {
    // 创建一个绑定函数,绑定第一个参数为 2
    auto boundFunc = std::bind(multiply, 2, std::placeholders::_1);

    // 将绑定函数赋值给 std::function
    std::function<int(int)> func = boundFunc;

    std::cout << "Multiply: " << func(5) << std::endl;  // 输出 10

    return 0;
}

4. 在容器中使用 std::function

std::function 可以与 STL 容器结合使用,例如在一个 vector 中存储多个可调用对象:

#include <iostream>
#include <functional>
#include <vector>

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

int subtract(int a, int b) {
    return a - b;
}

int main() {
    // 创建一个 std::function 向量
    std::vector<std::function<int(int, int)>> operations;

    // 将不同的函数添加到向量中
    operations.push_back(add);
    operations.push_back(subtract);

    int x = 10, y = 5;

    // 迭代并调用每个操作
    for (const auto& operation : operations) {
        std::cout << "Result: " << operation(x, y) << std::endl;  // 输出 5 和 15
    }

    return 0;
}

5. 性能考虑

  • 开销std::function 封装了可调用对象,因此在某些情况下可能会比直接使用函数指针稍慢,特别是在频繁调用的性能敏感场景中。
  • 内存使用std::function 在内部需要动态分配内存来存储可调用对象,这可能会增加内存开销。

6. 总结

  • 使用场景:如果您需要灵活性,想要能够存储多种类型的可调用对象,那么 std::function 是理想的选择。如果您只需要简单的函数调用并且对性能非常敏感,可以考虑使用函数指针。
  • 现代 C++ 的特性std::function 和 Lambda 表达式结合使用,能够让代码更加简洁和可读。它们使得函数式编程风格在 C++ 中变得更加自然。

希望这些详细的说明能帮助您更好地理解 std::function 和其与函数指针之间的区别!


原文地址:https://blog.csdn.net/sun_0228/article/details/142742376

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!