zoukankan      html  css  js  c++  java
  • 指针与引用(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 实现。

  • 相关阅读:
    CodeForces 706C Hard problem
    CodeForces 706A Beru-taxi
    CodeForces 706B Interesting drink
    CodeForces 706E Working routine
    CodeForces 706D Vasiliy's Multiset
    CodeForces 703B Mishka and trip
    CodeForces 703C Chris and Road
    POJ 1835 宇航员
    HDU 4907 Task schedule
    HDU 4911 Inversion
  • 原文地址:https://www.cnblogs.com/vizdl/p/13708811.html
Copyright © 2011-2022 走看看