在现实生活中,每个人都有一个名字,但是与我们关系不同的人,对我们的称呼是不一样的。例如:有个名叫张三的人,他的父母称呼他可能是小三、儿子,他的兄弟称呼他可能是三哥,当然在我们口中他也可能是法外狂徒。除了张三这个名字之外,其他的小三、三哥、法外狂徒都是他的别名。
在C++中,也提供了类似于别名的概念 — 引用
引用的基本语法
类型 & 别名 = 变量名
#includeusing namespace std; int main() { string sichuan = "四川"; string &sc = sichuan; cout<<"我是"< 注:
引用的使用
- &在此不是求地址运算,而是起标识作用。
- 类型标识符是指目标变量的类型
- 必须在声明引用变量时进行初始化。
- 引用初始化之后不能改变。
- 不能有NULL引用。必须确保引用是和一块合法的存储单元关联。
- 可以建立对数组的引用。
void test(){ int a = 10; //给变量a取一个别名b int& b = a; cout << "a:" << a << endl; cout << "b:" << b << endl; cout << "------------" << endl; //操作b就相当于操作a本身 b = 100; cout << "a:" << a << endl; cout << "b:" << b << endl; cout << "------------" << endl; //一个变量可以有n个别名 int& c = a; c = 200; cout << "a:" << a << endl; cout << "b:" << b << endl; cout << "c:" << c << endl; cout << "------------" << endl; //a,b,c的地址都是相同的 cout << "a:" << &a << endl; cout << "b:" << &b << endl; cout << "c:" << &c << endl; }数组的引用
void test2(){ //1. 建立数组引用方法一 typedef int ArrRef[10]; int arr[10]; ArrRef& aRef = arr; for (int i = 0; i < 10;i ++){ aRef[i] = i+1; } for (int i = 0; i < 10;i++){ cout << arr[i] << " "; } cout << endl; //2. 建立数组引用方法二 int(&f)[10] = arr; for (int i = 0; i < 10; i++){ f[i] = i+10; } for (int i = 0; i < 10; i++){ cout << arr[i] << " "; } }引用在函数中的使用引用最常用的地方是在函数参数和返回值中。当引用被用作函数参数的时,在函数内对任何引用的修改,将对还函数外的参数产生改变。当然,可以通过传递一个指针来做相同的事情,但引用具有更清晰的语法。
如果从函数中返回一个引用,必须像从函数中返回一个指针一样对待。当函数返回值时,引用关联的内存一定要存在。//值传递 void ValueSwap(int m,int n){ int temp = m; m = n; n = temp; } //地址传递 void PointerSwap(int* m,int* n){ int temp = *m; *m = *n; *n = temp; } //引用传递 void ReferenceSwap(int& m,int& n){ int temp = m; m = n; n = temp; } int main(){ int a = 10; int b = 20; //值传递 ValueSwap(a, b); cout << "a:" << a << " b:" << b << endl; //a:10 b:20 //地址传递 PointerSwap(&a, &b); cout << "a:" << a << " b:" << b << endl; //a:20 b:10 //引用传递 ReferenceSwap(a, b); cout << "a:" << a << " b:" << b << endl; //a:20 b:10 return 0; }通过引用参数产生的效果同按地址传递是一样的。引用的语法更清楚简单:
- 函数调用时传递的实参不必加“&”符
- 在被调函数中不必在参数前加“*”
- 不能返回局部变量的引用。
- 函数当左值,必须返回引用。
引用作为其它变量的别名而存在,因此在一些场合可以代替指针。C++主张用引用传递取代地址传递的方式,因为引用语法容易且不易出错。//返回局部变量引用 int& testFun01(){ int a = 10; //局部变量 return a; } //返回静态变量引用 int& testFunc02(){ static int a = 20; cout << "static int a : " << a << endl; return a; } int main(){ //不能返回局部变量的引用 int& ret01 = testFun01(); //如果函数做左值,那么必须返回引用 testFunc02(); testFunc02() = 100; testFunc02(); return 0; }指针引用在未接触到引用之前,我们要改变一个指针的指向,可能定义的函数:
void fun(int **);
使用引用之后,我们可以给指针取一个别名,定义的函数:
void func(int * &)#include常量引用using namespace std; struct Student{ int age; }; //指针间接修改teacher的年龄 void AllocateAndInitByPointer(Student** stu){ *stu = (Student*)malloc(sizeof(Student)); (*stu)->age = 18; } //引用修改teacher年龄 void AllocateAndInitByReference(Student*& stu){ stu->age = 20; } int main() { //创建Student Student* stu = NULL; //指针间接赋值 AllocateAndInitByPointer(&stu); cout << "AllocateAndInitByPointer:" << stu->age << endl; //引用赋值,将stu本身传到ChangeAgeByReference函数中 AllocateAndInitByReference(stu); cout << "AllocateAndInitByReference:" << stu->age << endl; free(stu); return 0; } 常量引用的定义格式:
const 类型& 别名 = 变量名;
常量引用注意:
- 字面量不能赋给引用,但是可以赋给const引用
- const修饰的引用,不能修改。
#includeusing namespace std; int main() { int a = 100; const int& aa = a; //此时aa就是a //aa = 200; 不能通过aa赋值 a = 100; //OK cout << "a:" << a << endl; cout << "aa:" << aa << endl; //不能把一个字面量赋给引用 //int& ref = 100; //但是可以把一个字面量赋给常引用 const int& ref = 100; return 0; } 将函数的形参定义为常量引用的好处:
- 引用不产生新的变量,减少形参与实参传递时的开销.
- 由于引用可能导致实参随形参改变而改变,将其定义为常量引用可以消除这种副作用。
如果希望实参随着形参的改变而改变,那么使用一般的引用,如果不希望实参随着形参改变,那么使用常引用。#includeusing namespace std; //const int& a防止函数中意外修改数据 void showVal(const int& a){ //a = 10; //error: assignment of read-only reference 'a' cout << "a:" << a << endl; } int main() { int a =100; showVal(a); return 0; }



