C++ 引用

引用可以简化原来使用指针的代码,至少看起来舒服点,不过今天发现个问题,先来看一段代码

C++ 引用
 1 #include <iostream>
 2 #include <cstdlib>
 3 #include <vector>
 4 
 5 using namespace std;
 6 
 7 int main() {
 8     vector<int> stack;
 9     
10     stack.push_back(1);
11     
12     int& rx = stack[0];
13     
14     int vx = stack[0];
15 
16     int vy = rx;
17 
18     cout<<rx<<endl;
19     
20     stack.pop_back();
21     
22     cout<<rx<<endl;
23     
24     stack.push_back(2);
25     
26     cout<<rx<<endl;
27     
28     system("pause");
29     return 0;
30 }
C++ 引用

输出:

1
1
2

可以看到引用的值发生了变化,并且在被引用值“不存在”的情况下也返回了一个值。我们说引用的值总是存在的,因此在不会出现NULL的地方且指向不变的地方可以用引用代替指针。实际上引用是一个指针,由于引用使用的语法的规则,它必须有初值(也就是说它不会为NULL),而它的作用域(生命周期)总是等于或小于被引用的变量,而且一旦指定被引用对象后无法改变,因而使用它比直接用指针来的安全。来看一下以上部分代码在VS2012中的反汇编

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    int& rx = stack[0];
00FC6495  push        0 
00FC6497  lea         ecx,[stack] 
00FC649A  call        std::vector<int,std::allocator<int> >::operator[] (0FC1276h) 
00FC649F  mov         dword ptr [rx],eax 
     
    int vx = stack[0];
00FC64A2  push        0 
00FC64A4  lea         ecx,[stack] 
00FC64A7  call        std::vector<int,std::allocator<int> >::operator[] (0FC1276h) 
00FC64AC  mov         eax,dword ptr [eax] 
00FC64AE  mov         dword ptr [vx],eax 
 
    int vy = rx;
00FC64B1  mov         eax,dword ptr [rx] 
00FC64B4  mov         ecx,dword ptr [eax] 
00FC64B6  mov         dword ptr [vy],ecx 

  

可以看到调用operator[]返回值存在eax中(函数调用约定),当初始化引用变量rx时,直接将eax给了rx,而当赋值给整型变量vx时,多了一句

1
013364AC  mov         eax,dword ptr [eax]

即将eax指向的内存内容重新赋值给eax,然后eax再把这个值给vx变量。从这里我们可以看出operator[]返回的eax实际上是一个指针,相应的引用rx也是一个指针,只不过在语法上做了限制,编译器做了检查和额外处理,让它用起来像一个普通值变量。比如语句

1
int vy = rx;

将一个引用赋值给一个整型变量,

1. 首先获得指向rx引用对象的指针 (mov eax,dword ptr [rx])

2. 然后根据指针值获得被引用对象的值 (mov ecx,dword ptr [eax])

3. 最后把值赋给变量vy (mov dword ptr [vy],ecx )

再来看一个指针版本的反汇编,就会发现与引用变量相关的汇编代码几乎是一致的。

1
2
3
4
5
6
7
8
    int* p = &stack[0];
00FC64BB  lea         ecx,[stack] 
00FC64BE  call        std::vector<int,std::allocator<int> >::operator[] (0FC1276h) 
00FC64C3  mov         dword ptr [p],eax 
    int vz = *p;
00FC64C6  mov         eax,dword ptr [p] 
00FC64C9  mov         ecx,dword ptr [eax] 
00FC64CB  mov         dword ptr [vz],ecx 

C++ 引用,布布扣,bubuko.com

C++ 引用

上一篇:Python tricks(7) -- new-style class的__slots__属性


下一篇:Recoil 中多级数据联动及数据重置的合理做法