C++中的引用是什么
主要是用来解决指针太麻烦的问题而设计的一种新的语法格式,本质上是指针常量。
相较于指针的优缺点
- 优点:避免指针的麻烦写法
- 缺点:无法改变引用的指向、必须声明时初始化
使用引用
引用的语法格式
数据类型 &引用名 = 原变量;
引用的特点
1 2 3
| int a = 3; int &ra; int &ra = a;
|
1 2
| int a = 3; long &lra = a;
|
1 2 3 4 5 6
| int a = 3, b = 4; int &ra = a; ra = b; std::cout << "ra: " << ra << std::endl; std::cout << "a: " << a << std::endl; std::cout << "b: " << b << std::endl;
|
引用作为函数参数
例子引入:交换两变量的值
1 2 3 4 5 6 7 8 9 10 11
| void SwapByPointer(int *pa, int *pb) { int t = *pa; *pa = *pb; *pb = t; }
int main() { SwapByPointer(&a, &b); return 0; }
|
1 2 3 4 5 6 7 8 9 10 11
| void SwapByReference(int &ra, int &rb) { int t = ra; ra = rb; rb = t; }
int main() { SwapByReference(a, b); return 0; }
|
例子引入:对传入字面量或常量的处理
1 2 3 4 5 6 7 8
| void PrintValue1(int &ra) { cout << "ra: " << ra << endl; }
int main() { PrintValue1(10); return 0; }
|
1 2 3 4 5 6 7 8 9 10
| void PrintValue2(const int &cra) { cout << "cra: " << cra << endl; }
int main() { int a = 20; PrintValue2(10); PrintValue2(a); return 0; }
|
原理:虽然说参数为常引用时,它本质还是指针,依然需要接收地址,但是 C++ 对策略是:当传入参数时, 如果传入的是一个右值, 那么将会有一个临时变量存放这个值, 并且引用将会绑定这个临时变量。
1 2 3
| int temp = 20; const int &cra = temp;
|
对指针的引用
语法格式
数据类型 *&引用名 = 原指针;
例子引入:在函数内改变指针的指向
1 2 3 4 5 6 7 8 9
| void Allocate1(int **pp) { *pp = new int(10); }
int main() { int *p1 = nullptr; Allocate1(&p1); return 0; }
|
1 2 3 4 5 6 7 8 9
| void Allocate2(int *&rp) { rp = new int(20); }
int main() { int *p2 = nullptr; Allocate1(p2); return 0; }
|
引用作为函数的返回值
返回一个有效引用的前提
如果要保证返回一个有效的引用,那么返回变量的生命周期必须要长于用于接收的引用,否则就是野指针。
返回引用的一些例子
1 2 3 4 5 6 7 8 9 10
| int& ReturnLocalVar() { int a = 10; return a; }
int main() { int &ra = ReturnLocalVar(); std::cout << "ra: " << ra << std::endl; }
|
1 2 3 4 5 6 7 8 9 10
| int& ReturnStaticVar() { static int a = 10; return a; }
int main() { int &ra = ReturnLocalVar(); std::cout << "ra: " << ra << std::endl; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| int& ReturnRefParam(int &ra, const int value) { ra = value; return ra; }
int main() { int c = 10; int &rc = ReturnRefParam(c, 20); cout << "rc: " << rc << endl;
ReturnRefParam(c, 30) = 40; cout << "rc: " << rc << endl; }
|
总结
- 引用的本质就是指针常量,但是对写法进行了包装,既有指针的功能,又简便了写法
- 引用必须在声明时初始化,且不能换绑或进行类型强转
- 可以对一级指针进行引用,以避免二级指针的写法,但注意声明语句的
*
一定是在 &
前面
- 注意作为引用返回的变量的生命周期,避免野指针