C++中的引用

原创 2012年03月26日 12:47:08

引用就是对象的另一个名字--这是《c++primer》中介绍引用里的一句话;而且很多c++参考书中都有“引用是另一个对象的别名”这一说;这句话很容易让人引起误会。看下面的例子:
int main()
{
 int a;
 int &b = a;

 a = 1;
 cout<<"a="<<a<<endl;
 cout<<"b="<<b<<endl;

 b = 2;
 cout<<"a="<<a<<endl;
 cout<<"b="<<b<<endl;
 
 cout<<"&a="<<&a<<endl;
 cout<<"&b="<<&b<<endl;

 return 0;
}
输出结果:
a=1
b=1
a=2
b=2
&a=0012FF7C
&b=0012FF7C

从上面看出,对a操作相当于对b操作,对b操作相当于对a操作,就好比b是a的影子,两者都会互相影响,但是影子和实物本质上还是有区别的,看如下会编代码:

1015:     int a;
1016:     int &b = a;
00401598   lea         eax,[ebp-4]
0040159B   mov         dword ptr [ebp-8],eax
这几行汇编代码中,先得到b(ebp-4)的地址赋给eax,然后eax赋给ebp-8(也就是a)。反正就是把b的地址赋给a,最后a里面存的是b的地址,而b里面呢,是数值(因为没初始化所以是一个int型的随机数)。到这里,你还认为a和b是一样的吗?
再看看下面的:

1026:     cout<<"&a="<<&a<<endl;
00401656   push        offset @ILT+200(std::endl) (004010cd)
0040165B   lea         edx,[ebp-4]             ;获取a的地址
0040165E   push        edx
0040165F   push        offset string "&a=" (0046f020)
00401664   push        offset std::cout (0047ce90)
00401669   call        @ILT+650(std::operator<<) (0040128f)
0040166E   add         esp,8
00401671   mov         ecx,eax
00401673   call        @ILT+60(std::basic_ostream<char,std::char_traits<char> >::operator<<) (00401041)
00401678   mov         ecx,eax
0040167A   call        @ILT+480(std::basic_ostream<char,std::char_traits<char> >::operator<<) (004011e5)
1027:     cout<<"&b="<<&b<<endl;
0040167F   push        offset @ILT+200(std::endl) (004010cd)
00401684   mov         eax,dword ptr [ebp-8]  ;&b操作,想想这里为什么不是lea eax    [ebp -8]呢,因为这里b是对a的引用
00401687   push        eax
00401688   push        offset string "&b=" (0046f01c)
0040168D   push        offset std::cout (0047ce90)
00401692   call        @ILT+650(std::operator<<) (0040128f)
00401697   add         esp,8
0040169A   mov         ecx,eax
0040169C   call        @ILT+60(std::basic_ostream<char,std::char_traits<char> >::operator<<) (00401041)
004016A1   mov         ecx,eax
004016A3   call        @ILT+480(std::basic_ostream<char,std::char_traits<char> >::operator<<) (004011e5)
从这段代码的结果看出&a和&b操作都是反回a的地址,但是过程不同,对于&a,它是lea   edx,[ebp-4];而&b,它是eax,dword ptr [ebp-8] 也就是b的值给eax。说明b存的是a的地址

1018:     a = 1;
0040159E   mov         dword ptr [ebp-4],1  ;对a的赋值
1019:     cout<<"a="<<a<<endl;
004015A5   push        offset @ILT+200(std::endl) (004010cd)
004015AA   mov         ecx,dword ptr [ebp-4]  ;对a的读取
004015AD   push        ecx
004015AE   push        offset string "a=" (0046f028)
004015B3   push        offset std::cout (0047ce90)
004015B8   call        @ILT+650(std::operator<<) (0040128f)
004015BD   add         esp,8
004015C0   mov         ecx,eax
004015C2   call        @ILT+255(std::basic_ostream<char,std::char_traits<char> >::operator<<) (00401104)
004015C7   mov         ecx,eax
004015C9   call        @ILT+480(std::basic_ostream<char,std::char_traits<char> >::operator<<) (004011e5)
1020:     cout<<"b="<<b<<endl;
004015CE   push        offset @ILT+200(std::endl) (004010cd)
004015D3   mov         edx,dword ptr [ebp-8]    ;  对b的读取代码
004015D6   mov         eax,dword ptr [edx]
004015D8   push        eax
004015D9   push        offset string "b=" (0046f024)
004015DE   push        offset std::cout (0047ce90)
004015E3   call        @ILT+650(std::operator<<) (0040128f)
004015E8   add         esp,8
004015EB   mov         ecx,eax
004015ED   call        @ILT+255(std::basic_ostream<char,std::char_traits<char> >::operator<<) (00401104)
004015F2   mov         ecx,eax
004015F4   call        @ILT+480(std::basic_ostream<char,std::char_traits<char> >::operator<<) (004011e5)
1021:
1022:     b = 2;
004015F9   mov         ecx,dword ptr [ebp-8]    ;对b赋值
004015FC   mov         dword ptr [ecx],2

从中看出对a的赋值代码,和对a的读取代码都是直接操作。而对b的读取和赋值操作中,先读取b中保存的值(a的地址)给edx,然后通过dword ptr [edx]完成读取,对于赋值也一样;

所以,对于a的赋值和读取操作,直接就可以;而对于b(它是引用),先要读取它里面的保存的值(也就是a的地址),然后根据这个地址进行读取和赋值操作。当然我们写代码时,完全可以把b当成a的一个别名来操作;

------本人菜鸟一个,有什么地方理解错了,望大牛指出

C++之引用的详解

详细剖析c++中的引用,消除心中久疑虑,拨开云雾见天明。交流学习,共同进步。...
  • Xiao__Tian__
  • Xiao__Tian__
  • 2016年07月03日 12:46
  • 11070

C++ : 引用的实质理解 !!!!

引用的定义:在类型和标识符之间加上一个取地址符,说明该标识符为指定类型的引用         如: int &ref = num;   就是ref是一个int型的引用     引用有什么作用呢?...
  • cy_weiyi
  • cy_weiyi
  • 2015年07月12日 17:09
  • 327

C++中引用是用来做什么用的,有什么好处

C语言没有引用,C++才有. 引用能起到指针的部分作用,但是比指针安全. 一个引用可以看作是某个变量的一个"别名"。对引用进行操作就像对原变量进行操作一样。 主要用于函数的参数传递时...
  • lee1054908698
  • lee1054908698
  • 2012年03月08日 09:52
  • 5820

C++中指针和引用的区别(超详细)

指针和引用主要有以下区别: 引用必须被初始化,但是不分配存储空间。指针不声明时初始化,在初始化的时候需要分配存储空间。 引用初始化后不能被改变,指针可以改变所指的对象。 不存在指向空值的...
  • weikangc
  • weikangc
  • 2015年11月10日 17:40
  • 994

C++引用本质

在看这篇文章之前,请你先要明白一点:那就是c++为我们所提供的各种存取控制仅仅是在编译阶段给我们的限制,也就是说是编译器确保了你在完成任务之前的正确行为,如果你的行为不正确,那么你休想构造出任何可执行...
  • zhubosa
  • zhubosa
  • 2013年09月09日 20:58
  • 2040

C++之类对象的返回与引用

一、类对象的返回 在拷贝构造器中提到过:class A{}; A func(A a){ return a; }int main(){ A x; func(x); }调用fun...
  • maoliran
  • maoliran
  • 2016年05月30日 11:19
  • 3220

[引用区别] c++中引用与java中引用区别

在Java中,类实例声明和构造是分开。"T a;"是声明,而"a=new T();"才是构造。引用声明和C++相同。但是Java的机制与C++不同,Java中的引用也叫句柄,或者说句柄才是其真实名称。...
  • WaitForFree
  • WaitForFree
  • 2016年03月31日 21:08
  • 3489

C++中<>和“”引用头文件的区别

以前在引用头文件时,总是不假思索的使用和“”是一样的。但其实不然,是从标准类库中引用头文件,而我们自己在工程自己创建的没有加入到标准类库中的头文件是无法引用的,这种情况下,我们必须要用“”进行引用~...
  • qwezhaohaihong
  • qwezhaohaihong
  • 2017年07月26日 14:54
  • 263

C++中引用之常引用

引用&分为普通引用和常引用。 知识架构: void main() { //普通引用 int a = 10; int &b = a; printf("b:%d \n", b); //常引...
  • patkritLee
  • patkritLee
  • 2016年02月17日 22:54
  • 1500

C++的数组元素为什么不能是引用类型

感谢原作者分享:http://blog.xinspace.space/2015/01/25/cpp-array-element-not-ref/ 这几天在看c++基础内容,看到数组的...
  • fukaibo121
  • fukaibo121
  • 2017年07月31日 22:15
  • 654
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C++中的引用
举报原因:
原因补充:

(最多只允许输入30个字)