C++指针:从内存寻址到函数调用的实战指南

C++指针:从内存寻址到函数调用的实战指南 1. 指针的本质内存地址的身份证每次我给别人解释指针时最喜欢用的比喻就是身份证。想象一下变量就像一个人而指针就是这个人的身份证号码。身份证号码本身不是人但它能唯一标识一个人在哪里。指针也是如此——它存储的不是实际数据而是数据在内存中的门牌号。来看个最简单的例子int age 25; int* agePtr age;这里age是个整型变量存储着值25。age获取的是age在内存中的地址比如0x7ffeee3b4a5cagePtr就是存储这个地址的指针变量。就像你不会把身份证号码和真人搞混一样在C中也要清楚区分指针和它指向的值。我第一次用指针时犯的典型错误是int* ptr; *ptr 10; // 灾难指针还没指向合法内存这就像拿着空白身份证非要说是某个人系统当然会报错。正确做法是先让指针指向有效的内存地址。2. 指针操作从基础到进阶2.1 指针的基本操作指针最常用的三个操作取地址获取变量的内存地址解引用*通过指针访问指向的值指针赋值改变指针指向的位置看个实际场景——交换两个变量的值void swap(int* a, int* b) { int temp *a; // 解引用获取值 *a *b; *b temp; } int x 5, y 10; swap(x, y); // 传递地址2.2 指针与数组的暧昧关系数组名本质上就是个常量指针。当我第一次发现arr[i]和*(arri)完全等价时简直像发现了新大陆int nums[3] {10, 20, 30}; int* ptr nums; // 等价于 nums[0] cout nums[1] endl; // 20 cout *(ptr 1) endl; // 20但要注意指针和数组的关键区别指针是变量可以重新赋值数组名是常量不能改变指向2.3 指针的算术运算指针加减不是简单的数值运算而是以指向类型的大小为单位移动。这是我初学时踩过的坑double values[5] {1.1, 2.2, 3.3, 4.4, 5.5}; double* ptr values; ptr; // 不是地址1而是8因为double占8字节3. 动态内存管理指针的主战场3.1 new和delete的正确姿势动态内存分配是指针最重要的用途之一。记得我第一个内存泄漏的程序void leaky() { int* ptr new int[100]; // 忘记delete[] ptr; }正确的做法应该是int* createArray(int size) { int* arr new int[size]; // 初始化... return arr; } void demo() { int* myArr createArray(100); // 使用数组... delete[] myArr; // 必须配对使用 }3.2 智能指针现代C的救星自从用了unique_ptr和shared_ptr我的内存管理轻松多了#include memory void safeDemo() { // 自动管理内存 auto ptr std::make_uniqueint[](100); // 不需要手动delete // 当ptr离开作用域时会自动释放内存 }4. 高级指针技巧4.1 函数指针把函数当参数传递函数指针让我实现了类似JavaScript的回调功能void process(int x, int y, int (*operation)(int, int)) { cout 结果是 operation(x, y) endl; } int add(int a, int b) { return a b; } int multiply(int a, int b) { return a * b; } // 使用 process(3, 4, add); // 输出7 process(3, 4, multiply); // 输出124.2 多级指针指针的指针当需要修改指针本身时就需要用到指针的指针void allocate(int** ptr) { *ptr new int(42); // 修改外部指针的指向 } int main() { int* p nullptr; allocate(p); // 传递指针的地址 cout *p endl; // 42 delete p; }5. 常见指针陷阱与防御5.1 空指针和野指针空指针用nullptr表示是安全的int* ptr nullptr; if (ptr) { // 安全的检查 // 只有当ptr非空时才执行 }野指针则极其危险int* danger; // 未初始化 *danger 10; // 未定义行为5.2 const与指针的四种组合const和指针的组合经常让人困惑int value 10; const int* ptr1 value; // 指向常量值不能改 int* const ptr2 value; // 常量指针指向不能改 const int* const ptr3 value; // 都不可改5.3 内存泄漏检测技巧我常用的简单检测方法在new/delete前后打印内存使用情况使用工具如ValgrindLinux或Visual Studio的内存诊断工具尽量使用RAII资源获取即初始化技术指针就像C中的瑞士军刀功能强大但需要小心使用。经过多年的实践我发现最好的指针使用策略是能用引用就用引用必须用指针时优先考虑智能指针万不得已再用裸指针。记住每个new都应该有对应的delete就像每扇打开的门都应该关上一样。