引用介绍引用和指针常量
引用介绍引用分为左值引用和在C++11中提出的右值引用,在默认情况下谈及引用均指左值引用。
引用的作用类似于获取变量的地址,是给已声明的变量起别名的一种方法,引用类型引用(refer to)引用另一种类型。引用类型变量的声明格式是将在变量名左边添加&符号,即&D的形式,其中D是引用类型的变量名。
int i = 1; int &r1 = i; //r1引用变量i,是i的别名
引用必须初始化,且一个变量引用另一个变量之后,就和该变量绑定在一起,不能再引用背的变量。
引用并非一个对象,而只是已有对象的一个别名。
引用和指针常量为什么引用必须初始化?一个引用真的只能绑定到一个对象上?引用为变量取一个别名,不是对象,那么它究竟是什么?程序编译后引用变量以什么形式存在?它和普通变量有什么区别?
如果你能清楚回答以上问题,那么下面的内容就不用看了,否则,让我们一起揭开引用的神秘面纱。
int i = 7; int &r = i; r = 8;
上面的代码片段在VS2013 环境下反汇编得到的80386汇编代码为
int i = 7; 00D752C8 mov dword ptr [i],7 //将文字常量7放入变量i的地址所表示的内存单元中 int &r = i; 00D752CF lea eax,[i] //将变量i的地址放入寄存器eax中 00D752D2 mov dword ptr [r],eax //将eax中的值,也就是变量i的地址放入变量r的地址所指示的内存单元中 r = 8; 00D752D5 mov eax,dword ptr [r] //将变量r的地址所指示的内存单元中的值,也就是变量i的地址放入寄存器eax 00D752D8 mov dword ptr [eax],8 //将文字常量8放入寄存eax的值(变量i的地址)所指示的内存单元中
从上述汇编代码可以看出,引用本身也是一个变量,其所代表的内存单元中存放的是引用变量所引用的对象的内存地址。
引用变量和指针常量是等价的吗?
int j = 6; int *const p = &j; *p = 9;
上述代码片段对应的汇编代码为
14: 15: int j = 6; 003552BE mov dword ptr [j],6 16: int *const p = &j; 003552C5 lea eax,[j] 003552C8 mov dword ptr [p],eax 17: 18: *p = 9; 003552CB mov eax,dword ptr [p] 003552CE mov dword ptr [eax],9
可见引用在内部实现时与指针常量等价。引用和指针常量的区别体现在高级语言层面,指针常量允许寻址,即&i输出的是变量ide地址,但引用变量不允许寻址,&r输出的是变量i的地址而不是变量引用变量r的地址。引用变量r的地址对程序员不可见,由编译器生成。
下面的代码段输出同样的值。
int i = 7; int &r = i; r = 8; std::cout << &r << std::endl; std::cout << &i << std::endl;
引用能用常量指针实现,但是常量指针能实现的功能未必可以用引用实现,如下面的代码片段。
//定义一个元素类型为常量指针的数组 int i =1; int j = 2; int *cosnt a[] = {&i, &j}
下面的代码片段无法编译通过。
//不能编译通过,无法定义引用的数组 int i =1; int j = 2; int & a[] = {i, j}
综上所述,引用可以视作指针常量,但是两者不完全等同,引用无法实现指针常量的全部功能。
基于上述结论,以下问题便迎刃而解了。
引用不能独立于所引用的对象存在,因为引用变量要求获取引用对象的地址值。
不能返回函数内部非静态局部变量的引用,因为非静态局部变量在函数调用结束后即被销毁,地址不存在。但是可以返回函数内部局部变量,普通的局部变量的生命周期会被编译器自动延长,类对象类型的局部变量会执行拷贝构造函数和析构函数。
不能将一个引用变量绑定多个变量,因为引用变量存储的是引用对象的地址,是一个指针常量,指针值不能改变。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)