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. 重要注意事项
🚫 避免的陷阱
- 不要返回局部变量的地址
- 不要返回局部数组的指针
- 动态分配的内存必须记得释放
✅ 最佳实践
- 优先使用返回值而不是返回指针
- 使用引用参数来修改外部变量
- 必要时使用智能指针管理动态内存
- 函数指针使用typedef提高可读性
编译警告
使用 -Wall 选项编译可以检测悬挂指针问题:
g++ -Wall -o program main.cpp
总结
| 技术 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 返回值指针 | 灵活 | 易产生悬挂指针 | 一般不推荐 |
| 动态内存 | 控制生命周期 | 需手动管理内存 | 需要长期存在的数据 |
| 静态变量 | 简单安全 | 全局状态,线程不安全 | 单线程简单场景 |
| 参数传递 | 最安全 | 需要预先定义变量 | 推荐使用 |
| 函数指针 | 实现回调 | 语法复杂 | 策略模式、回调机制 |
推荐优先使用参数传递和直接返回值的方式,避免不必要的指针操作。

被折叠的 条评论
为什么被折叠?



