1. 概述
引用的作用是给 变量 起一个 别名.
比如 int a = 10;
a 就是这个变量的名称, 程序通过 操作 a 来操作 a代表的内存空间.
但可以通过引用, 让 b 也能代表这块空间, 然后就可以通过 b 来操作这段内存.
语法:
数据类型 &别名 = 原名;
int a = 10;//int &b = 10; 非法引用, 10并不存放在变量区.int &b = a;
2. 引用的注意事项
1. 引用必须要经过初始化;
2. 引用在初始化之后, 就不可以更改.
a 和 c 的定义过程已省略.
int &b; //错误, 引用必须初始化, 没有原名的引用是非法的.int &b = a;int &b = c; //错误, 引用之后就不可以更改了.b = c; //正确, 因为这不是引用, 而是把 c 的值赋给 b.
3. 引用传递
详见函数篇C++ 函数_AusrEnder的博客-CSDN博客
4. 引用作函数返回值
不要返回局部变量的引用
这和 栈区 的释放机制有关, 与 不要返回局部变量的地址 是一个道理.
子函数结束后, 通过引用或者地址访问局部变量地址都是非法的, 因为栈内存已经释放.
局部变量的保存与否, 取决于编译器. 所以最好不要这样做.
#includeusing namespace std;//不要返回局部变量的引用.//int & 类型作为返回类型, 说明函数返回的是局部变量的引用.int& function(){ int a = 10; return a;}int main(){ int& ref = function(); cout << ref << endl; cout << ref << endl; return 0;}
如果一定要返回怎么办呢?
很简单, 不要让局部变量存放在栈区中就可以了.
已知局部常量也存放在栈区, 而静态变量存放于全局区, 所以用 static 修饰局部变量即可.
同时, 因为函数表达式就是返回值, 返回值类型为引用, 因此函数表达式等于变量名, 可以赋值.
#includeusing namespace std;//不要返回局部变量的引用.//int & 类型作为返回类型, 说明函数返回的是局部变量的引用.int& function(){ int a = 10; return a;}int& function1(){ static int a = 20; // static 修饰 表示这是一个静态变量, 存放于全局区 return a;}int main(){ int& ref = function(); cout << ref << endl; //栈内存已经释放, 这是非法访问 cout << ref << endl; int& ref1 = function1(); cout << ref1 << endl; // static 静态变量 存放于全局区, 即便栈区内存释放, 也不受影响, 访问合法 function1() = 1000; // 引用作返回值时, 函数表达式相当于一个变量名, 因此可以作为左值,对其进行赋值. cout << ref1 << endl; //输出 1000 , 因为此时 ref1 和 function1 都为该段内存的变量名. cout << function1() << endl; //输出 1000 , 因为此时 ref1 和 function1 都为该段内存的变量名. return 0;}
5. 引用的本质
引用在 C++ 内部本质是一个指针常量.
int a = 0;int &ref = a; //编译器自动转换为 int * const ref = &a;ref = 20; //编译器发现 ref 是引用, 自动转换为 *ref = 20;
//发现是引用传递, 转换为 int * const ref = &a;void function(int &ref){ ref = 100; //转换为 *ref = 100} int main(){ int a = 10; function(a); return 0 ;}
6. 常量引用
引用传递和地址传递一样会影响实参, 若又想保护实参, 又不想用值传递, 就可以用
const 修饰的指针来地址传递. 当然, 也可以用 const 修饰的引用传递.
(因为指针常量只保护指针指向, 不保护指向的值.)
void function(const int &ref){ ref++; //报错,因为 const 修饰引用, ref不是可以修改的左值.}
int a = 10;//int &b = 10; //非法引用, 10并不存放在变量区.int &b = a; //int & ref = 10; //非法引用, 同上const int & ref = 10; //合法引用, 编译器分配临时变量名并引用. //转换为 int temp = 10; const int & ref = temp; //再转换为 const int * const ref = &temp;ref = 20; //报错, 常量引用后 ref 的值不可以修改.