1. 引用
1.1 引用
引用:就是别名,就是变量的别名。
(1)定义变量num与初始化变量num的别名rnum int num = 1; int &rnum = num; (2)给变量num赋值: num = 10; =>num = 10; rnum = 10; (3)给别名rnum赋值: rnum = 100; =>num = 100; rnum = 100;
1.2 指针与引用的区别
- 指针:
(1)就是用来保存内存地址的变量;
(2)指针进行删除操作后,需要将它们赋为空,也就是说指针可以为空;
(3)指针可以被赋值;
(4)如果想使一个变量记录不同对象的地址,那么就必须使用指针; - 引用:
(1)就是用来作为变量的别名,它们标识的内存地址是一样的;
(2)引用不需要作置空处理,因为引用是原来对象的别名;
假如该对象存放在栈中:那么在对象超出作用域时别名会和对象一起消失;
假如该对象存放在堆中:由于堆中内存空间必须使用指针来访问,因此用不着别名,即使再定义一个该指针的别名,那么将指针删除并赋空后,该指针的别名中的地址也相应的赋空了;
(3)引用只能被初始化,不可以被赋为另一个对象的别名;
(4)引用不能指向不同的对象;
1.3 引用就是别名常量
- 定义了某个变量的别名,那么该别名就永远属于这个变量。一个别名只能对应一个变量,不能同时作为多个变量的别名,而一个变量可以有多个别名。
定义引用时,一定要对该引用进行初始化。引用就如同常量,只能对其初始化,不能对其赋值。
(1)正确的例子: int a; int &ra = a; (2)错误的例子: int a; int &ra; ra = b;
1.4 引用、指针与堆空间
在堆中创建一块内存区域,必须要用指针来指向它,否则该区域就会变成无法访问的内存空间。当然也可以使用引用来引用指向内存空间的指针。
int *p = new int; int &r = *p; //这样r就成了指针p读取到的值的别名 r = 4; cout<<*p; //*p 和 r 的值都是4
我们不可以直接用引用来指向堆中新建的空间,因为引用只是个别名,它不可以作为指针来使用。如int &r = new int;这是错误的。正确的写法是int *&r = new int;定义了r为新空间的别名。
#include <iostream> using namespace std; int main() { int *&r = new int; *r = 6; cout<<"读取新建空间地址处的值:"<<*r<<endl; cout<<"输出新建空间的地址:"<<r<<endl; cout<<"读取r地址处的值:"<<*&r<<endl; cout<<"r的内存地址:"<<&r<<endl; return 0; } =>读取新建空间地址处的值:6 输出新建空间的地址:00031148 读取r地址处的值:00031148 r的内存地址:0013FF78 (1)*r:用星号来*访问r,就是访问堆中空间的数据; (2)r:保存的是堆中空间的地址; (3)&r:由于"&r"前加了个星号*,那么&r就是一个指针变量,获取系统自动为这个变量分配的内存地址,就像获取一个指针变量的内存地址一样,如int* p; cout<<&p;; (4)*&r:就是读取堆中空间的地址,与r一样;
注:上述例子建议不要使用,明白原理即可
(1)正常情况下: 定义了r为新空间的别名;
(2)不正常的情况下: 也就是机器虚拟内存太小,无法创建新空间的情况下,那么new int会自动返回一个空指针。引用不能为空, 因此在这种情况下使用语句int * &r = new int;就会导致产生一个无用的别名。而是用星号(”*“ ) 读取一个无用的别名则会引起系统崩溃。
解决方法: 就是不要将引用初始化为新建内存区域的别名,而将r初始化为指向该区域的指针的别名。
int *p = new int;
if (p != null)
{
int &r = *p;
}
1.5 常引用的定义
- 常引用:用这种方式声明的引用,不能通过引用对目标变量的值进行修改,从而使引用的目标成为const,达到了引用的安全性。
常引用声明方式:const 类型标识符 &引用名=目标变量名;
int a; const int &ra=a; ra=1; //错误,由于引用定义为常引用,因此不能通过引用对目标变量的值进行修改 a=1; //正确
- 常引用的作用:避免通过别名的方式修改变量的值。
参考文献:
[1]《C++全方位学习》范磊——第九章
[2]《C++程序设计教程(第二版)》钱能——第三章
[3] 百度搜索关键字:C++引用、引用与指针的区别、常引用