指针本质是显式暴露变量的内存地址,入门关键在于建立“地址→值”映射直觉;声明int p;仅定义指针变量,必须初始化为&valid_int或nullptr,避免野指针;在声明中表类型,在表达式中表解引用,语义由位置决定。

指针不是“学不会”,而是没踩对起点——它根本就不是新概念,只是把变量背后的内存地址显式暴露出来。你早就在用地址了,比如数组下标 arr[0],本质就是编译器帮你算好了 &arr[0];函数传参时拷贝整个结构体很慢?那直接传地址更快。入门的关键不是背符号,是建立“地址→值”的映射直觉。
怎么定义和初始化一个合法的指针变量
声明时写 int* p;,这只是告诉编译器“我要存一个 int 类型变量的地址”;但此时 p 里是随机值(野指针),不能碰。必须立刻初始化:
- 指向已有变量:
int a = 42; int* p = &a;——&a是取地址操作,类型必须匹配(int*不能存&c,除非c是int) - 明确不指向任何东西:
int* p = nullptr;—— 推荐用nullptr而非NULL或0,类型安全 - 别写成
int* p, q;:这声明的是一个指针p和一个普通int变量q,想两个都是指针得写int* p, *q;
为什么 *p 有时是声明、有时是解引用
同一个星号 *,位置不同,语义完全不同:
- 在类型后面、变量名前面:
int* p;→ 声明,表示“p是个指针” - 在已定义的指针变量前:
*p = 100;或cout → 解引用,表示“去p存的地址里读/写值” - 常见误判:看到
char* s = "hello";就以为s是字符串——其实s是个地址,"hello"是只读内存里的字符数组首地址,*s才是'h'
传参时用指针改原变量,为什么不能只传值
C++ 默认值传递,函数内修改形参不影响实参。想改外面的变量,就得告诉函数“它的地址在哪”:
- 错误示范:
void inc(int x) { x++; }→ 调用inc(a)后a不变 - 正确做法:
void inc(int* x) { (*x)++; }→ 调用inc(&a),*x就是a本身 - 注意检查空指针:
if (x != nullptr) { (*x)++; },否则inc(nullptr)会崩溃 - 现代 C++ 更倾向用引用:
void inc(int& x) { x++; },语义更清晰,且编译器能更好优化
最容易被忽略的三个细节
新手常卡在这儿,不是语法错,是理解断层:
-
sizeof(p)永远是 8(64 位系统),和它指向的类型无关——指针本身只存地址,不管地址里是int还是double - 数组名
arr不是指针变量,但可隐式转为&arr[0];sizeof(arr)返回整个数组字节数,sizeof(&arr[0])才是 8 - 野指针比空指针更危险:空指针一解引用就崩(容易发现),野指针可能指向刚释放的内存或别的变量,改着改着数据就错乱,且不一定立刻暴露
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











