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的博客-优快云博客
4. 引用作函数返回值
不要返回局部变量的引用
这和 栈区 的释放机制有关, 与 不要返回局部变量的地址 是一个道理.
子函数结束后, 通过引用或者地址访问局部变量地址都是非法的, 因为栈内存已经释放.
局部变量的保存与否, 取决于编译器. 所以最好不要这样做.
#include <iostream>
using namespace std;
//不要返回局部变量的引用.
//int & 类型作为返回类型, 说明函数返回的是局部变量的引用.
int& function()
{
int a = 10;
return a;
}
int main()
{
int& ref = function();
cout << ref << endl;
cout << ref << endl;
return 0;
}
如果一定要返回怎么办呢?
很简单, 不要让局部变量存放在栈区中就可以了.
已知局部常量也存放在栈区, 而静态变量存放于全局区, 所以用 static 修饰局部变量即可.
同时, 因为函数表达式就是返回值, 返回值类型为引用, 因此函数表达式等于变量名, 可以赋值.
#include <iostream>
using 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 的值不可以修改.