简体   繁体   English

指令集如何区分参考值

[英]How do instruction sets differentiate value from reference

Let's look at this code: 让我们看一下这段代码:

int main ()
{
    int a = 5;
    int&b = a;

    cout << a << endl;  // 5 is displayed
    cout << b << endl;  // 5 is also displayed

    return 0;
}

This is the behavior I saw in my debugger. 这是我在调试器中看到的行为。

int a = 5 will assign value 5 in memory address -0x14(%rbp) int a = 5将在内存地址-0x14(%rbp)中分配值5

int& b = a will assign value -0x14(%rbp) in memory address -0x8(%rbp) int& b = a将分配值-0x14(%rbp)在存储器地址-0x8(%RBP)

When I do cout << a << endl the value in the address of a (ie -0x14(%rbp)) will be displayed. 当我cout << a << endl ,将显示a地址(即-0x14(%rbp))中的值。

But somehow when I do cout << b << endl the value in the address of b (ie -0x8(%rbp) ) is determined to be an address then the value of that address ( -0x14(%rbp) ) is displayed. 但是以某种方式,当我执行cout << b << endl ,确定b地址中的值(即-0x8(%rbp) )是一个地址,然后显示该地址的值( -0x14(%rbp) ) 。

This is the assembly for the std::cout calls: 这是std :: cout调用的程序集:

20                  cout << a << endl;
0000000000401506:   mov -0xc(%rbp),%eax
0000000000401509:   mov %eax,%edx
000000000040150b:   lea 0x6f8c9c6e(%rip),%rcx        # 0x6fccb180 <libstdc++-6!_ZSt4cout>
0000000000401512:   callq 0x4015f8 <_ZNSolsEi>
0000000000401517:   lea 0xe2(%rip),%rdx        # 0x401600 <_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_>
000000000040151e:   mov %rax,%rcx
0000000000401521:   callq 0x401608 <_ZNSolsEPFRSoS_E>
21                  cout << b << endl;
0000000000401526:   mov -0x8(%rbp),%rax
000000000040152a:   mov (%rax),%eax
000000000040152c:   mov %eax,%edx
000000000040152e:   lea 0x6f8c9c4b(%rip),%rcx        # 0x6fccb180 <libstdc++-6!_ZSt4cout>
0000000000401535:   callq 0x4015f8 <_ZNSolsEi>
000000000040153a:   lea 0xbf(%rip),%rdx        # 0x401600 <_ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_>
0000000000401541:   mov %rax,%rcx
0000000000401544:   callq 0x401608 <_ZNSolsEPFRSoS_E>
24                  return 0;

Question: 题:

Both std::cout instructions are very similar, How is a treated differently from b ? 两条std :: cout指令都非常相似, ab有何区别?

In short: it does not. 简而言之:事实并非如此。

CPU itself doesn't care about which type is stored where, it just executes instructions generated by compiler. CPU本身并不关心哪种类型存储在哪里,它只执行编译器生成的指令。

Compiler knows that b is a reference, not an int . 编译器知道b是一个引用,而不是int So it instructs CPU to treat b as a pointer. 因此,它指示CPU将b视为指针。

If you look at the assembly code for your program, you'll see that the instructions for accessing a and b are different: the part for b contains an extra instruction 如果查看程序的汇编代码,则会看到访问ab的指令是不同的: b的部分包含一条额外的指令。

mov (%rax),%eax

which is the dereferencing step. 这是取消引用的步骤。 (In this assembly notation, parentheses mean dereferencing, so this instruction means something like eax = *rax). (在该汇编符号中,括号表示取消引用,因此此指令含义类似于eax = * rax)。

I presume you've requested absolutely no optimization. 我想您绝对没有要求优化。 Although even then, I would have expected accessing a and accessing b to generate exactly the same code (in this case, at least). 尽管即使那样,我仍希望访问ab来生成完全相同的代码(至少在这种情况下)。

With regards to how the compiler knows: a and b have different types, so the compiler knows to do different things with them. 关于编译器如何知道: ab具有不同的类型,因此编译器知道对它们执行不同的操作。 The standard has been designed so that replacing int& with int* const , and then automatically dereferencing on each access (except the initialization) will result in a conforming implementation; 该标准经过精心设计,可以用int& int* const替换int& ,然后在每次访问时自动取消引用(初始化除外)将产生符合要求的实现; it looks like this is what your compiler is doing. 看起来这就是您的编译器正在执行的操作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM