
这是 C 最核心、也最让新手头疼的一章。但别怕我们用门牌号的类比一步步讲到彻底理解。掌握它你就跨过了 C 最大的门槛。8.1 内存地址数据的门牌号第 3 章说过内存像一个大储物柜每个格子有地址门牌号。intx42;这句做了两件事找一个空格子把 42 放进去。这个格子的门牌号地址就是x能取到的值。取地址运算符可以得到变量的地址intx42;std::coutxstd::endl;// 打印 x 的地址形如 0x7ffd3a2b...地址是一串十六进制数指向内存中的某个位置。8.2 指针专门存地址的变量指针pointer就是一个存地址的变量。intx42;int*px;// p 是指向 int 的指针存的是 x 的地址拆解int* p x;int*类型表示指向 int 的指针p变量名x取出 x 的地址现在p里存着 x 的门牌号。指针就是门牌号的副本。解引用*通过门牌号找到房间有了门牌号怎么进去看/改房间里的东西用解引用运算符*intx42;int*px;std::cout*pstd::endl;// 42*p 就是p 指向的那个值*p100;// 通过指针修改 xstd::coutxstd::endl;// 100x 被改了*p读作p 指向的内容。通过*p可以读写 x就像直接操作 x 一样。和*是一对反操作x拿到 x 的地址问x 住哪*p拿到地址 p 指向的值问这个门牌号住的是谁一张图记住变量 x ── 存着 42 变量 p ── 存着 x 的地址 ──→ 指向 x *p x 的值428.3 为什么需要指针你可能想问直接用变量不就行了为什么要绕一圈用指针原因有几个在函数里修改外部的值见 8.5避免复制大数据把一个巨大的数组/矩阵传给函数时传地址比复制整个数据快得多动态分配内存第 11 章实现复杂数据结构链表、树等这些场景后面都会遇到。现在先掌握指针的基本操作。8.4 空指针 nullptr指针如果不指向任何东西应该给它赋nullptr空指针表示不指向任何地方int*pnullptr;// 空指针访问空指针是严重错误程序崩溃。所以解引用前要检查if(p!nullptr){std::cout*pstd::endl;// 安全}8.5 指针与函数真正修改外部变量第 6 章说值传递改不了外部变量。用指针就能改#includeiostreamvoidaddOne(int*p){*p*p1;// 通过指针修改 p 指向的那个变量}intmain(){intx5;addOne(x);// 传入 x 的地址std::coutx;// 6x 被真正修改了}8.6 引用更优雅的别名指针好用但*、写起来繁琐易错。C 提供了引用reference——给变量起别名intx42;intrx;// r 是 x 的引用别名r 和 x 是同一个东西r100;std::coutx;// 100通过 r 改 x引用和指针的区别指针引用语法int* p x;用*p访问int r x;直接用r能否为空可以为nullptr不能为空必须绑定一个变量能否改指向能指向别的变量一旦绑定终身不改可读性繁琐更简洁引用的本质就是变量的另一个名字操作r就是操作x。8.7 引用参数函数里改外部变量推荐写法用引用传参函数里就能改外部变量而且语法干净#includeiostreamvoidswap(inta,intb){// 引用参数inttmpa;ab;btmp;}intmain(){intx1,y2;swap(x,y);std::coutx y;// 2 1交换成功}8.8 常量引用只读 高效传大对象时既想不复制高效又不想让函数修改它就用常量引用voidprint(conststd::strings){// const // s 可以读但不能改std::coutsstd::endl;}const std::string读作“一个字符串的只读引用”。这是 C 里极其常见的写法Eigen 里到处都是如const MatrixXd务必熟悉。记忆口诀看到const X就理解为传了个地址进去但保证不改它既快又安全。8.9 指针的指针、指针与数组了解指针可以指向指针多级指针数组名其实是指向首元素的指针inta[3]{10,20,30};int*pa;// 数组名 a 就是首元素地址std::cout*p;// 10std::coutp[1];// 20指针也能用下标这些是底层细节初学了解即可后面用std::vector会更省心。8.10 小结指针int* p存地址x取地址*p解引用。指针能改外部变量、避免复制、动态分配内存。引用int r是别名不能为空、不能改绑。常量引用const T只读 高效Eigen 里极常用。空指针nullptr解引用前先判空。下一章学习结构体与类——把相关的数据打包成一个整体。练习题声明int x 10; int* p x;通过*p把 x 改成 20打印验证。写函数increment(int n)用引用参数让外部变量加 1。写函数print(const std::string s)打印字符串体会常量引用。用指针写swap交换两个 int 的值。说说引用和指针的三点区别。