[英]How do instruction sets differentiate value from reference
让我们看一下这段代码:
int main ()
{
int a = 5;
int&b = a;
cout << a << endl; // 5 is displayed
cout << b << endl; // 5 is also displayed
return 0;
}
这是我在调试器中看到的行为。
int a = 5
将在内存地址-0x14(%rbp)中分配值5
int& b = a
将分配值-0x14(%rbp)
在存储器地址-0x8(%RBP)
当我cout << a << endl
,将显示a地址(即-0x14(%rbp))中的值。
但是以某种方式,当我执行cout << b << endl
,确定b地址中的值(即-0x8(%rbp)
)是一个地址,然后显示该地址的值( -0x14(%rbp)
) 。
这是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;
题:
两条std :: cout指令都非常相似, a
与b
有何区别?
简而言之:事实并非如此。
CPU本身并不关心哪种类型存储在哪里,它只执行编译器生成的指令。
编译器知道b
是一个引用,而不是int
。 因此,它指示CPU将b
视为指针。
如果查看程序的汇编代码,则会看到访问a
和b
的指令是不同的: b
的部分包含一条额外的指令。
mov (%rax),%eax
这是取消引用的步骤。 (在该汇编符号中,括号表示取消引用,因此此指令含义类似于eax = * rax)。
我想您绝对没有要求优化。 尽管即使那样,我仍希望访问a
和b
来生成完全相同的代码(至少在这种情况下)。
关于编译器如何知道: a
和b
具有不同的类型,因此编译器知道对它们执行不同的操作。 该标准经过精心设计,可以用int&
int* const
替换int&
,然后在每次访问时自动取消引用(初始化除外)将产生符合要求的实现; 看起来这就是您的编译器正在执行的操作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.