C/C++ 指针与函数

1. 返回值是指针的函数(易产生悬挂指针)

❌ 错误示例:返回局部变量的地址

#include <iostream>
using namespace std;

// 危险!返回局部变量的地址
int* dangerous_func() {
    int a = 10;          // 局部变量,函数结束即销毁
    cout << "函数内a的地址: " << &a << ", 值: " << a << endl;
    return &a;           // 返回已被销毁的内存地址
}

// 另一个函数,可能重用相同内存
int* another_dangerous_func() {
    int b = 20;
    cout << "函数内b的地址: " << &b << ", 值: " << b << endl;
    return &b;
}

void demo_dangling_pointer() {
    cout << "=== 悬挂指针演示 ===" << endl;
    
    int* pa = dangerous_func();
    cout << "pa指向地址: " << pa << ", 值: " << *pa << endl; // 未定义行为!
    
    int* pb = another_dangerous_func();
    cout << "pb指向地址: " << pb << ", 值: " << *pb << endl; // 未定义行为!
    
    cout << "再次访问pa: " << *pa << endl; // 可能显示随机值
    cout << endl;
}

✅ 正确解决方案

方案1:动态内存分配
int* safe_func_dynamic() {
    int* p = new int(100);  // 在堆上分配内存
    cout << "动态分配地址: " << p << ", 值: " << *p << endl;
    return p;               // 安全返回
}

void demo_dynamic_memory() {
    cout << "=== 动态内存方案 ===" << endl;
    
    int* p = safe_func_dynamic();
    cout << "获取的值: " << *p << endl;
    
    delete p;  // 必须手动释放!
    cout << endl;
}
方案2:静态变量(有限使用)
int* safe_func_static() {
    static int value = 200;  // 静态变量,生命周期与程序相同
    cout << "静态变量地址: " << &value << ", 值: " << value << endl;
    return &value;
}

void demo_static_variable() {
    cout << "=== 静态变量方案 ===" << endl;
    
    int* p = safe_func_static();
    cout << "获取的值: " << *p << endl;
    cout << endl;
}
方案3:传递参数(推荐)
void safe_func_param(int& result) {
    result = 300;  // 通过引用修改外部变量
    cout << "参数地址: " << &result << ", 设置值: " << result << endl;
}

void demo_parameter_passing() {
    cout << "=== 参数传递方案 ===" << endl;
    
    int value;
    safe_func_param(value);
    cout << "最终值: " << value << endl;
    cout << endl;
}

2. 指向函数的指针

基本用法

#include <iostream>
using namespace std;

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

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

void demo_function_pointer() {
    cout << "=== 函数指针演示 ===" << endl;
    
    
    
    // 定义一个指向函数的指针,注意,这是一个指针!
    typedef int (*MathFunc)(int, int);
    /*
    ()优先级大于 * 运算符
    int *MathFunc(int,int)
    -->这是一个函数声明:返回值是int*的函数,函数名为MathFunc,参数为两个int
    
    int (*MathFunc)(int,int)
    -->(*MathFunc)告诉大家,我是一个名为MathFunc的指针,是什么类型的指针呢?
    -->(*MathFunc)()后面有个括号,原来是指向函数的指针。那这个函数是有什么参数,以及返回值是多少呢?
    	ps:(*parr)[] 后面有个中括号,指向数组的
    -->int (*MathFunc)(int,int)-->指针指向的函数的参数是两个int变量,返回值是int。
    */
    
    // 声明函数指针变量
    MathFunc funcPtr = nullptr;
    
    // 指向add函数
    funcPtr = add;
    cout << "加法结果: " << funcPtr(5, 3) << endl;
    
    // 指向multiply函数
    funcPtr = multiply;
    cout << "乘法结果: " << funcPtr(5, 3) << endl;
    cout << endl;
}

函数指针作为参数

// 计算器函数,接收函数指针作为参数
void calculator(int a, int b, int (*operation)(int, int)) {
    int result = operation(a, b);
    cout << a << " 和 " << b << " 的运算结果: " << result << endl;
}

void demo_callback() {
    cout << "=== 回调函数演示 ===" << endl;
    
    calculator(10, 5, add);        // 传递add函数
    calculator(10, 5, multiply);   // 传递multiply函数
    cout << endl;
}

函数指针数组

void demo_function_array() {
    cout << "=== 函数指针数组 ===" << endl;
    
    // 定义函数指针数组
    int (*operations[2])(int, int) = {add, multiply};
    
    for (int i = 0; i < 2; i++) {
        cout << "操作" << i+1 << "结果: " << operations[i](6, 4) << endl;
    }
    cout << endl;
}

3. 完整测试程序

int main() {
    // 演示悬挂指针问题
    demo_dangling_pointer();
    
    // 演示正确解决方案
    demo_dynamic_memory();
    demo_static_variable();
    demo_parameter_passing();
    
    // 演示函数指针
    demo_function_pointer();
    demo_callback();
    demo_function_array();
    
    return 0;
}

4. 重要注意事项

🚫 避免的陷阱

  1. 不要返回局部变量的地址
  2. 不要返回局部数组的指针
  3. 动态分配的内存必须记得释放

✅ 最佳实践

  1. 优先使用返回值而不是返回指针
  2. 使用引用参数来修改外部变量
  3. 必要时使用智能指针管理动态内存
  4. 函数指针使用typedef提高可读性

编译警告

使用 -Wall 选项编译可以检测悬挂指针问题:

g++ -Wall -o program main.cpp

总结

技术优点缺点适用场景
返回值指针灵活易产生悬挂指针一般不推荐
动态内存控制生命周期需手动管理内存需要长期存在的数据
静态变量简单安全全局状态,线程不安全单线程简单场景
参数传递最安全需要预先定义变量推荐使用
函数指针实现回调语法复杂策略模式、回调机制

推荐优先使用参数传递和直接返回值的方式,避免不必要的指针操作。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值