C++函数 第六课
《神奇的双胞胎名字——引用传递(Reference Passing)》
本课学习目标
学完本课,同学们能够:
✅ 理解为什么需要引用传递
✅ 理解引用(Reference)是变量的"别名"
✅ 掌握引用传递的写法
✅ 能解释引用传递为什么能够修改外部变量
✅ 能区分值传递和引用传递
第一幕:复制魔法太麻烦了
1、上一节课,我们学会了值传递。
(1)画图。
a = 10 ↓ 复制 ↓ x = 10(2)修改:
x = 100;(3)最后:
a = 10 x = 100(4)函数结束。
x 消失(5)所以:
外面的:
a 没有变化。2、汉克老师问大家:
如果说:
"我就是要修改a!"
怎么办?
复制。
显然做不到。
第二幕:程序王国的新魔法
1、国王请来了最厉害的大魔法师。
他说:
"以后不要复制了。"
大家都愣住了。
那怎么办?
2、魔法师说:
"给它再起一个名字!"
画图。
(1)以前:
a 10(2)现在:
a 10 ↑ ↓ x(3)注意!
不是两个变量。
而是:
一个变量。
两个名字。
3、汉克老师给同学们讲:
引用不是新变量。
引用只是变量的另一个名字。
第三幕:生活中的别名
1、例如:
(1)一个同学。
大名:
张小明(2)家里叫:
明明(3)学校同学叫:
小明(4)是不是三个人?
当然不是。
(5)还是:
同一个人。
只是:
三个名字。
引用就是这样。
2、变量也是这样:
一个变量,通过引用,也可以有几个名字。
第四幕:认识"&"
我们开始写代码。
#include <iostream> using namespace std; void change(int &x) { x = 100; } int main() { int a = 10; change(a); cout << a << endl; return 0; }(1)运行后:
100全班同学都会惊讶了,
为什么?
(2)汉克老师画图。
以前:
a ↓ 复制 ↓ x现在:
a ↑ ↓ x没有复制。
所以:
修改:
x = 100;其实就是:
a = 100;第五幕:"&"是什么意思?
1、很多老师都会讲到:
"&" 就是取地址。
汉克老师这里一定要强调:
在这里:
int &x里面的:
&表示:
引用。
2、意思就是:
给原来的变量起一个新的名字。
并不是创建一个新的变量。
第六幕:引用传递全过程
我们画一下完整流程。
main a = 10 ↓ change() ↓ x ↓ 其实就是a ↓ x = 100 ↓ a也变成100 ↓ 函数结束 ↓ a仍然100第七幕:交换两个数字
1、值传递
void swap(int a,int b) { int t = a; a = b; b = t; }调用:
int x = 3; int y = 8; swap(x,y);输出:
3 8为什么没交换?
因为:
复制。
2、引用传递
void swap(int &a,int &b) { int t = a; a = b; b = t; }调用:
swap(x,y);输出:
8 3真正交换成功。
第八幕:值传递 VS 引用传递
1、画图。
(1)值传递:
a ↓ 复制 ↓ x(2)引用传递:
a ↑ ↓ x2、一句话总结:
值传递:
变量复制后,复制件传过去。
引用传递:
变量自己传过去。
第九幕:为什么引用更快?
1、举例。
一本:
1000页。
百科全书。
2、两种方式进行比较
(1)使用值传递:
复制一本。
(2)引用传递:
直接借原书。
(3)哪个快?
引用传递快
3、所以,大型数据。
例如:
数组。
vector。
字符串。
一般:
都用引用传递。
第十幕:什么时候应该用引用?
1、如果,希望修改外面的变量。
例如:
交换。
排序。
输入。
统计。
适合:
引用传递。
2、如果,只是使用变量的值,不需要修改变量。
值传递也可以。
第十一幕:引用有没有危险?
1、如果,很多函数,都能修改同一个变量。
(1)是不是:
有可能:
被不小心修改了?
(2)所以。
引用:
虽然方便。
但是:
要注意,不能乱改。
2、看代码:
#include <iostream> #include <string> using namespace std; // 函数声明:使用 const 引用传递参数 // const int& a: 表示 a 是传入变量的别名,且在该函数内不可被修改 // const int& b: 同理 int add(const int& a, const int& b) { // a = 10; // 错误!编译器会报错,因为 a 是 const 引用,不能修改 return a + b; } // 对于大型对象(如 string),const 引用的优势更明显 void printMessage(const string& msg) { // msg += " extra"; // 错误!不能修改 msg cout << "Message: " << msg << endl; } int main() { int x = 10; int y = 20; // 调用函数 int sum = add(x, y); cout << "Sum: " << sum << endl; // 传递普通变量 string text = "Const reference is safe."; printMessage(text); return 0; }3、const引用参数传递的重要性
(1)性能优化:避免不必要的拷贝
值传递的问题:如果使用值传递,每次调用函数时,编译器都会创建实参的一个完整副本。对于基本类型(如
int、double),拷贝开销很小;但对于大型对象(如string、vector、自定义类对象),拷贝涉及内存分配和数据复制,效率极低。引用的优势:引用传递(
&)不创建副本,因此速度极快。结论:使用引用传递可以显著提升程序运行效率,特别是当参数是大对象时。
(2)安全性:防止意外修改实参
普通引用的风险:如果使用非
const引用(如void func(int& a)),函数内部可以直接修改传入的变量。这可能导致意想不到的副作用,破坏原始数据。const 的保护作用:加上
const后(const int& a),编译器会强制检查函数体内部是否尝试修改该参数。如果有修改操作,编译阶段就会报错。const提供了“只读”保证,增强了代码的健壮性和安全性,明确告知调用者:“我只读取数据,不会改变它”。
第十二幕:课堂综合案例
1、成绩加分程序
#include <iostream> using namespace std; void addScore(int &score) { score += 5; } int main() { int score = 90; cout << "加分前:" << score << endl; addScore(score); cout << "加分后:" << score << endl; return 0; }运行结果:
加分前:90 加分后:95让同学们画图:
score 90 ↑ ↓ score(引用) ↓ 95同学们理解了:
修改的是同一个变量。
第十三幕:值传递与引用传递对比实验
#include <iostream> using namespace std; void fun1(int x) { x++; } void fun2(int &x) { x++; } int main() { int a = 10; fun1(a); cout << a << endl; fun2(a); cout << a << endl; return 0; }运行结果:
10 11同学们来解释下:
为什么第一次没变?
为什么第二次变了?
学生请画出"复制"和"别名"两张图。
本课总结
今天,我们学习了程序王国一种新的魔法——引用传递。请记住五句话:
引用不是创建新变量,而是给原变量起一个新的名字(别名)。
引用传递不会复制数据。
修改引用,就是修改原变量。
引用传递通常比值传递效率更高,特别适合较大的数据。
是否修改原变量,是选择值传递还是引用传递的重要依据。
防止意外修改实参,可以使用
const引用。
课堂挑战
1、请编写下面两个函数:
void addOne1(int x); void addOne2(int &x);2、然后分别调用:
int n = 20; addOne1(n); cout << n << endl; addOne2(n); cout << n << endl;3、思考:
为什么第一次输出还是20,第二次却变成了21?
4、同学们,建立下面两张"心智模型图":
(1)值传递
实参 │ │ 复制 ▼ 形参(2)引用传递
实参 ▲ │ ▼ 形参(别名)📚 课后拓展
引用已经不用复制了,那为什么 C++ 还有"指针传递"呢?
"引用像是给朋友起了一个小名,而指针更像是拿到了一张写着家庭住址的纸条。下节课,我们就去学习程序王国里神奇的'地址魔法'——指针传递。"