指针与引用(gcc如何实现引用的)

   首先,变量名在编译成汇编语言的时候,会被翻译成地址。

 例如 :

1 void square() {
2     int var = 0;
3 }

   会被翻译成 :

1 square():
2         push    rbp
3         mov     rbp, rsp
4         mov     DWORD PTR [rbp-4], 0
5         nop
6         pop     rbp
7         ret

   rbp - 4 在这里就是变量名 var 翻译而成的,而 DWORD PTR [rbp - 4]就是变量值。

   而指针类型的变量名也会翻译成地址,但是这个指针变量值也是一个地址。

1 void square() {
2     int var = 0;
3     int * pointer = &var;
4 }

   会被翻译成 :

1 square():
2         push    rbp
3         mov     rbp, rsp
4         mov     DWORD PTR [rbp-12], 0
5         lea     rax, [rbp-12]
6         mov     QWORD PTR [rbp-8], rax
7         nop
8         pop     rbp
9         ret

  在这里, rbp-12就是变量名 var 翻译而成的。

  int * pointer = &var;
  被翻译成了
  lea rax, [rbp-12]
  mov QWORD PTR [rbp-8], rax
  而指针变量名pointer 被翻译成 rbp - 8。 指针变量pointer 的值是 rbp-12。

  引用与指针的区别在哪呢?

  引用与变量名一样都是地址。

  例如 :

1 void square() {
2     int var = 0;
3     int &ref = var;
4     int * pointer = &ref;
5 }

   会被翻译成 :

 1 square():
 2         push    rbp
 3         mov     rbp, rsp
 4         mov     DWORD PTR [rbp-20], 0
 5         lea     rax, [rbp-20]
 6         mov     QWORD PTR [rbp-8], rax
 7         mov     rax, QWORD PTR [rbp-8]
 8         mov     QWORD PTR [rbp-16], rax
 9         nop
10         pop     rbp
11         ret

  int * pointer = &ref;

  被翻译成:

  mov rax, QWORD PTR [rbp-8]

  mov QWORD PTR [rbp-16], rax

  其中 rbp - 8是一个指针变量 &ref,而 [rbp - 8]的值是  rbp - 20, 在这里 QWORD PTR [rbp-8]其实就是引用ref也就是 rbp - 20。 而实现的具体方法就是利用指针变量 rbp-8来实现的。

  所以创建引用所需要的内存等于指针变量所需要的内存(因为在gcc中是利用指针实现引用的)。在其他平台则不一定。

pass by reference (to const)

  如若形参列表是引用形式,那么在gcc中会传入什么呢?

  如下 : add函数。

1 int add (const int& a, const int& b){
2     return a + b;
3 }
4 
5 void test (){
6     add(1,2);
7 }

  会被翻译成 :

 1 add(int const&, int const&):
 2         push    rbp
 3         mov     rbp, rsp
 4         mov     QWORD PTR [rbp-8], rdi
 5         mov     QWORD PTR [rbp-16], rsi
 6         mov     rax, QWORD PTR [rbp-8]
 7         mov     edx, DWORD PTR [rax]
 8         mov     rax, QWORD PTR [rbp-16]
 9         mov     eax, DWORD PTR [rax]
10         add     eax, edx
11         pop     rbp
12         ret
13 test():
14         push    rbp
15         mov     rbp, rsp
16         sub     rsp, 16
17         mov     DWORD PTR [rbp-8], 2
18         mov     DWORD PTR [rbp-4], 1
19         lea     rdx, [rbp-8]
20         lea     rax, [rbp-4]
21         mov     rsi, rdx
22         mov     rdi, rax
23         call    add(int const&, int const&)
24         nop
25         leave
26         ret

  在上述汇编代码中,rsi 和 rdi 是 add 函数的实参。而汇编代码中 17,18行表示1,2两个常量分别存储在test函数栈中 rbp - 4, rbp - 8 的位置。

  汇编代码中 19,20,21,22行则利用 lea 指令将  rbp - 4, rbp - 8 的地址作为参数传入到 add 函数中去了。

  所以 pass by reference (to const) 传入的是指针。

以上所有解释都基于 gcc 实现。

 

posted @ 2020-09-21 21:38  Vizdl  阅读(441)  评论(0编辑  收藏  举报