我想更好地理解引用,所以我使用了一些 C++ 代码来查看引用和指针之间的差异,当它们编译为程序集(-O3)时,我意识到它们都给出了相同的汇编代码。
我很好奇当我们使用引用而不是指针作为参数时,是否有任何函数会给出不同的汇编代码。
通过示例更容易理解:(我使用 godbolt 来查看汇编输出。)
struct someStruct
{
int a;
int* ptr;
someStruct* next;
};
int f1(someStruct* v)
{
v->a = v->next->a + *v->next->ptr;
v->ptr = v->next->ptr;
v->next = v;
return v->a;
}
int f1(someStruct& v)
{
v.a = v.next->a + *v.next->ptr;
v.ptr = v.next->ptr;
v.next = &v;
return v.a;
}
这两个函数都给出相同的汇编 x86 代码:
f1(someS*): # @f1(someS*)
mov rcx, qword ptr [rdi + 16]
mov rdx, qword ptr [rcx + 8]
mov eax, dword ptr [rdx]
add eax, dword ptr [rcx]
mov dword ptr [rdi], eax
mov qword ptr [rdi + 8], rdx
mov qword ptr [rdi + 16], rdi
ret
bool f(int& x) { return &x != nullptr; }
bool g(int* x) { return x != nullptr; }
第一个函数必须始终返回
true
,因为引用必须始终绑定到对象。指向对象的指针(由 &x
构成)永远不会有空指针值。
另一方面,指针变量也可以有空指针值,因此
g
可能会也可能不会返回 true
。
编译器(可能在任何非零优化级别)都知道引用和指针之间的差异,因此将优化
f
以独立于参数返回 true
,而 g
将包含条件的实际测试.