C++ 入门学习经验 05——指针(一):从交换变量开始,搞懂值传递、指针和引用

C++ 入门学习经验 05——指针(一):从交换变量开始,搞懂值传递、指针和引用
大家好啊这里是土豆的博客一个正在努力学习技术的大学生。前面两篇我们聊了递归也用几个例子看到了有时候代码只是顺序换了一下结果就完全不一样。那今天这篇咱们来聊另一个很多初学者都会遇到的问题为什么我在函数里面明明改了变量回到主函数里却一点变化都没有这个问题其实特别适合用来引出 C 里面几个很重要的概念值传递、指针和引用。这几个东西刚开始看确实容易绕但只要从“函数到底拿到的是什么”这个角度去理解就会清楚很多。好了废话不多说咱们直接开始。简单案例交换函数我们先看一段代码。你觉得它会输出什么#include iostream using namespace std; void swap(int a, int b) { int temp a; a b; b temp; } int main() { int x 3, y 5; swap(x, y); cout x y endl; // 期待输出 5 3 ? return 0; }先暂停一下自己想一想。运行结果其实是3 5—— 完全没有交换。怎么回事明明 swap 函数里已经交换了a 和 b为什么外面的 x 和 y 没变这就要引出初学者最容易踩的第一个坑值传递。下面我们就开始讲讲要怎么理解这部分内容值传递函数里的变量是“复印件”在 C 里如果我们直接把变量传给函数比如swap(x, y)函数里面的a和b并不是原来的x和y而是它们的副本。可以这样理解你把一份资料复印给别人别人把复印件改得再多也不会影响你手里的原件。所以刚才那段代码真正发生的过程大概是这样main里面有两个变量x 3y 5。调用swap(x, y)时把x和y的值复制了一份分别给了a和b。函数里面交换的是a和b这两个副本。函数结束后a和b被销毁。原来的x和y从头到尾都没有被改过。所以这就是我们常说的函数里改了外面却没变。那如果我就是想让函数真的改到外面的变量该怎么办呢很自然的想法就是不要只给函数一份复印件而是告诉它原变量在哪里。这就引出了指针。指针保存地址的变量指针这个词刚听起来可能有点抽象但先不用想得太复杂。咱们可以先记住一句话指针就是用来保存地址的变量。比如int x 10; int* p x;这里有两个符号需要注意x表示取出变量x的地址。int* p表示p是一个指针变量它里面存的是一个int类型变量的地址。那既然p里面存着x的地址我们就可以通过p找到x这一步叫解引用cout *p endl; // 输出 10这里的*p就可以理解成顺着 p 里面保存的地址找到那个变量的值。所以如果要真正交换两个变量就可以把变量的地址传进函数void swapByPointer(int* a, int* b) { int temp *a; *a *b; *b temp; } ​ int main() { int x 3, y 5; swapByPointer(x, y); cout x y endl; return 0; }这次输出就是5 3因为函数拿到的不再是x和y的复印件而是它们的地址。函数通过地址找到了原变量所以修改就真的生效了。不过大家可能也发现了指针写起来会多一些*和刚开始很容易看晕。那有没有一种写法既能改到原变量又看起来更像普通变量呢有这就是引用。引用给变量起一个“别名”引用可以简单理解成给一个变量起了另一个名字。比如int x 10; int ref x; ref 20; ​ cout x endl; // 输出 20这里ref是x的引用也就是x的别名。我们修改ref其实就是在改x。所以交换两个变量时也可以这样写void swapByReference(int a, int b) { int temp a; a b; b temp; } ​ int main() { int x 3, y 5; swapByReference(x, y); cout x y endl; return 0; }这次同样会输出5 3引用的好处就是调用的时候很自然还是直接写swapByReference(x, y)但是函数内部拿到的不是副本而是原变量的别名。所以我觉得初学的时候可以这样记值传递看成复印件指针 地址引用 别名。三种方式简单对比为了方便理解咱们放在一起看一下方式函数参数写法调用时写法能不能改外面的变量值传递int afunc(x)不能指针传递int* afunc(x)能引用传递int afunc(x)能这里最容易混的地方就是两个在int ref x;里面表示引用。在x里面表示取地址。它们长得一样但出现在不同位置时意思是不一样的。这个刚开始不用死记硬背多看几段代码就会慢慢熟悉。指针和引用还有一个重要区别引用和指针都能让函数改到外面的变量但它们并不完全一样。引用一般定义时就要绑定到一个变量并且后面不能再改成引用别的变量int x 10, y 20; int ref x; ref y; // 这不是让 ref 改绑到 y而是把 y 的值赋给 x而指针就更灵活一点它可以先指向x后面再指向y也可以指向空int x 10, y 20; int* p x; p y; p nullptr;所以简单来说引用更像固定的别名用起来简洁。指针更像可以改变方向的地址变量更灵活但也更需要小心。至于什么时候用指针什么时候用引用这个后面结合数组、函数返回值、动态内存的时候会更好理解。今天先把最基础的概念弄清楚就行。写在最后今天咱们从一个简单交换函数的例子入手搞清楚了值传递类比复印件不改原件。指针传递传地址能改原件但写法稍复杂。引用传递别名能改原件写法简洁。所以只是参数的形式换一下——加个或*结果就不一样了。后面我们会继续聊数组与指针的关系、动态内存分配等等。如果你对指针还觉得晕没关系多练习写几遍自然就熟了。如果这篇文章对你有帮助麻烦点赞、关注和收藏吧谢谢有什么问题或者想法欢迎在评论区留言我们一起交流我们下篇见