第5天:引用
学习目标
掌握引用的概念和使用场景,理解引用与指针的区别,学会在函数中正确使用引用。
学习资源链接
📚 官方文档和教程
🎥 视频教程
📖 深入阅读
学习内容
1. 引用基础概念
- 引用的定义和声明
- 引用的初始化规则
- 引用与别名的概念
- 引用的限制
2. 引用与指针的区别
3. 引用作为函数参数
- 引用参数的优势
- 避免拷贝开销
- 修改原始变量
- 常量引用参数
4. 引用作为返回值
- 返回引用的条件
- 左值引用返回
- 链式调用
- 返回引用的陷阱
5. 常量引用
- const引用的作用
- 临时对象绑定
- 参数传递优化
- 只读访问保护
重点概念和代码示例
引用基础
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| #include <iostream> using namespace std;
void referenceBasics() { cout << "=== 引用基础 ===" << endl; int value = 42; int& ref = value; cout << "value = " << value << endl; cout << "ref = " << ref << endl; cout << "&value = " << &value << endl; cout << "&ref = " << &ref << endl; ref = 100; cout << "修改ref后,value = " << value << endl; int another = 200; ref = another; cout << "赋值后,value = " << value << endl; }
|
引用与指针对比
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| void referenceVsPointer() { cout << "\n=== 引用与指针对比 ===" << endl; int x = 10, y = 20; int* ptr = &x; cout << "指针: *ptr = " << *ptr << endl; ptr = &y; cout << "重新指向后: *ptr = " << *ptr << endl; *ptr = 30; cout << "修改后 y = " << y << endl; int& ref = x; cout << "引用: ref = " << ref << endl; ref = y; cout << "赋值后 x = " << x << endl; int* nullPtr = nullptr; cout << "指针大小: " << sizeof(ptr) << " bytes" << endl; cout << "引用大小: " << sizeof(ref) << " bytes (与所引用对象相同)" << endl; }
|
引用作为函数参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| void passByValue(int x) { x = 100; }
void passByReference(int& x) { x = 100; }
void passByConstReference(const int& x) { cout << "常量引用值: " << x << endl; }
void processString(const string& str) { cout << "字符串长度: " << str.length() << endl; }
void referenceParameters() { cout << "\n=== 引用作为函数参数 ===" << endl; int value = 42; cout << "原始值: " << value << endl; passByValue(value); cout << "值传递后: " << value << endl; passByReference(value); cout << "引用传递后: " << value << endl; passByConstReference(value); string longString = "这是一个很长的字符串,用来演示引用传递的效率优势"; processString(longString); }
|
引用作为返回值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| class IntArray { private: int data[10]; int size; public: IntArray() : size(0) {} int& operator[](int index) { if (index >= 0 && index < 10) { return data[index]; } throw out_of_range("Index out of range"); } const int& operator[](int index) const { if (index >= 0 && index < 10) { return data[index]; } throw out_of_range("Index out of range"); } IntArray& push_back(int value) { if (size < 10) { data[size++] = value; } return *this; } void print() const { for (int i = 0; i < size; i++) { cout << data[i] << " "; } cout << endl; } };
void referenceReturns() { cout << "\n=== 引用作为返回值 ===" << endl; IntArray arr; arr.push_back(1).push_back(2).push_back(3); cout << "链式添加后: "; arr.print(); arr[0] = 100; arr[1] = 200; cout << "修改后: "; arr.print(); }
|
常量引用的特殊用法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| void constReferenceSpecial() { cout << "\n=== 常量引用特殊用法 ===" << endl; const int& ref1 = 42; const int& ref2 = 3 + 4; cout << "临时对象引用: " << ref1 << endl; cout << "表达式引用: " << ref2 << endl; double pi = 3.14159; const int& intRef = pi; cout << "类型转换引用: " << intRef << endl; const string& tempStr = string("Hello") + " World"; cout << "临时字符串: " << tempStr << endl; }
|
实践练习
练习1:引用基础操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| void exercise1() { cout << "\n=== 练习1:引用基础操作 ===" << endl; int a = 10, b = 20; int& refA = a; cout << "初始值 a = " << a << ", refA = " << refA << endl; refA += 5; cout << "refA += 5 后,a = " << a << endl; refA = b; cout << "refA = b 后,a = " << a << ", b = " << b << endl; cout << "&a = " << &a << ", &refA = " << &refA << endl; cout << "地址相同: " << (&a == &refA) << endl; }
|
练习2:函数参数优化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| double calculateDistance1(pair<double, double> p1, pair<double, double> p2) { double dx = p1.first - p2.first; double dy = p1.second - p2.second; return sqrt(dx * dx + dy * dy); }
double calculateDistance2(const pair<double, double>& p1, const pair<double, double>& p2) { double dx = p1.first - p2.first; double dy = p1.second - p2.second; return sqrt(dx * dx + dy * dy); }
void exercise2() { cout << "\n=== 练习2:函数参数优化 ===" << endl; pair<double, double> point1 = {0.0, 0.0}; pair<double, double> point2 = {3.0, 4.0}; double dist1 = calculateDistance1(point1, point2); double dist2 = calculateDistance2(point1, point2); cout << "距离计算结果1: " << dist1 << endl; cout << "距离计算结果2: " << dist2 << endl; cout << "结果相同: " << (dist1 == dist2) << endl; }
|
练习3:实现swap函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| template<typename T> void mySwap(T& a, T& b) { T temp = a; a = b; b = temp; }
void exercise3() { cout << "\n=== 练习3:实现swap函数 ===" << endl; int x = 100, y = 200; cout << "交换前: x = " << x << ", y = " << y << endl; mySwap(x, y); cout << "交换后: x = " << x << ", y = " << y << endl; string s1 = "Hello", s2 = "World"; cout << "交换前: s1 = " << s1 << ", s2 = " << s2 << endl; mySwap(s1, s2); cout << "交换后: s1 = " << s1 << ", s2 = " << s2 << endl; }
|
练习4:链式操作类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| class Calculator { private: double value; public: Calculator(double initial = 0) : value(initial) {} Calculator& add(double x) { value += x; return *this; } Calculator& subtract(double x) { value -= x; return *this; } Calculator& multiply(double x) { value *= x; return *this; } Calculator& divide(double x) { if (x != 0) { value /= x; } return *this; } double getValue() const { return value; } void reset(double newValue = 0) { value = newValue; } };
void exercise4() { cout << "\n=== 练习4:链式操作类 ===" << endl; Calculator calc(10); double result = calc.add(5).multiply(2).subtract(3).divide(4).getValue(); cout << "链式计算结果: " << result << endl; calc.reset(100); result = calc.subtract(20).multiply(0.5).add(10).getValue(); cout << "第二次计算结果: " << result << endl; }
|
算法练习题
LeetCode相关题目
- 反转字符串 - 使用引用交换字符
- 移动零 - 引用优化数组操作
- 两数之和 II - 引用返回结果
练习5:实现高效的数组操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
| class EfficientArray { private: vector<int> data; public: int& at(size_t index) { if (index >= data.size()) { throw out_of_range("Index out of range"); } return data[index]; } const int& at(size_t index) const { if (index >= data.size()) { throw out_of_range("Index out of range"); } return data[index]; } EfficientArray& push_back(int value) { data.push_back(value); return *this; } int& find(int value) { for (auto& element : data) { if (element == value) { return element; } } throw runtime_error("Value not found"); } size_t size() const { return data.size(); } void print() const { for (const auto& element : data) { cout << element << " "; } cout << endl; } };
void exercise5() { cout << "\n=== 练习5:高效数组操作 ===" << endl; EfficientArray arr; arr.push_back(1).push_back(2).push_back(3).push_back(4).push_back(5); cout << "初始数组: "; arr.print(); arr.at(2) = 100; cout << "修改索引2后: "; arr.print(); try { arr.find(4) = 400; cout << "查找并修改4为400后: "; arr.print(); } catch (const exception& e) { cout << "错误: " << e.what() << endl; } }
|
常见错误与注意事项
1. 引用未初始化
1 2 3 4 5 6 7
| void referenceErrors() { int value = 10; int& ref = value; }
|
2. 返回局部变量的引用
1 2 3 4 5 6 7 8 9 10
| int& dangerousFunction() { int local = 42; return local; }
int& safeFunction(int& param) { return param; }
|
3. 常量引用绑定
1 2 3 4 5 6 7 8 9
| void constReferenceBinding() { int value = 10; const int& constRef = value; const int& tempRef = 42; }
|
学习检查点
完整示例程序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| #include <iostream> #include <vector> #include <stdexcept> #include <cmath> using namespace std;
int main() { cout << "=== C++ 引用学习 ===" << endl; referenceBasics(); referenceVsPointer(); referenceParameters(); referenceReturns(); constReferenceSpecial(); exercise1(); exercise2(); exercise3(); exercise4(); exercise5(); return 0; }
|
返回第一周 | 上一天:指针基础 | 下一天:动态内存分配