I wanted to understand references better so I played with some C++ code to see diffrence between references and pointers, when they compiled to assembly (-O3) I realized they both give the same assembly code.
I am curious about is there any function which gives diffrent assembly code when we use references instead of pointers as parameter.
Its more easy to understand with example: (I used godbolt to see assembly outputs.)
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;
}
This two functions both give this same Assembly x86 code:
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; }
The first function must always return true
because a reference must always be bound to an object. A pointer to an object (formed with &x
) has never a null pointer value.
A pointer variable on the other hand can have a null pointer value as well and so g
may or may not return true
.
Compilers (probably at any non-zero optimization level) are aware of this difference between references and pointers and therefore will optimize f
to return true
independent of the argument, while g
will contain an actual test of the condition.