Skip to main content

Pointers vs References in C/C++: An Assembly-Level Explanation

·675 words·4 mins
C C++ Pointers References Assembly
Table of Contents

In C++, both references and pointers can be used to pass variables into functions for modification. Consider these two versions of a simple swap function:

// Using a reference as a parameter
void swap_ref(int& a, int& b) {
    int temp = a;
    a = b;
    b = temp;
}

// Using a pointer as a parameter
void swap_ptr(int* a, int* b) {
    int temp = *a;
    *a = *b;
    *b = *a;
}

Both functions successfully swap two integers, but references allow direct naming of the underlying variable, while pointers require explicit dereferencing.

To understand their true differences, we can compile these functions with:

gcc -S file.c

This outputs the assembly code used by the compiler. Below is the generated (unoptimized) assembly.

Assembly Output Comparison
#

Assembly for swap_ref(int&, int&)
#

swap_ref(int&, int&):
        push    rbp
        mov     rbp, rsp
        mov     QWORD PTR [rbp-24], rdi
        mov     QWORD PTR [rbp-32], rsi
        mov     rax, QWORD PTR [rbp-24]
        mov     eax, DWORD PTR [rax]
        mov     DWORD PTR [rbp-4], eax
        mov     rax, QWORD PTR [rbp-32]
        mov     edx, DWORD PTR [rax]
        mov     rax, QWORD PTR [rbp-24]
        mov     DWORD PTR [rax], edx
        mov     rax, QWORD PTR [rbp-32]
        mov     edx, DWORD PTR [rbp-4]
        mov     DWORD PTR [rax], edx
        nop
        pop     rbp
        ret

Assembly for swap_ptr(int*, int*)
#

swap_ptr(int*, int*):
        push    rbp
        mov     rbp, rsp
        mov     QWORD PTR [rbp-24], rdi
        mov     QWORD PTR [rbp-32], rsi
        mov     rax, QWORD PTR [rbp-24]
        mov     eax, DWORD PTR [rax]
        mov     DWORD PTR [rbp-4], eax
        mov     rax, QWORD PTR [rbp-32]
        mov     edx, DWORD PTR [rax]
        mov     rax, QWORD PTR [rbp-24]
        mov     DWORD PTR [rax], edx
        mov     rax, QWORD PTR [rbp-32]
        mov     edx, DWORD PTR [rbp-4]
        mov     DWORD PTR [rax], edx
        nop
        pop     rbp
        ret

What We Learn
#

The two versions produce identical assembly instructions.

This demonstrates a key truth:

A C++ reference is implemented as a constant pointer at the machine level.

A reference is just a pointer whose address cannot be changed after initialization.

Why References Behave Like Constant Pointers
#

A reference:

  • Must be initialized immediately
  • Cannot be null (in normal usage)
  • Cannot be rebound to another variable

For example:

int x = 10;
int& ref = x;

Internally, this is equivalent to generating a hidden pointer:

int* const __ref = &x;

Whenever you use ref, the compiler automatically dereferences that hidden pointer.

This explains:

  • Why you can’t change what a reference refers to
  • Why references have no runtime overhead
  • Why the assembly is the same as using pointers

References: Restrictions That Make Them Safer
#

Although references and pointers both access variables indirectly, references impose useful constraints:

| Feature | Reference | Pointer | | - | | - | | Must be initialized | ✔️ Yes | ❌ No | | Can be null | ❌ No | ✔️ Yes | | Can be rebound | ❌ No | ✔️ Yes | | Pointer arithmetic | ❌ No | ✔️ Yes | | Always safe to use without null check | ✔️ Yes | ❌ No |

References are essentially auto-dereferenced pointers with safety rules.

Why C Has Only Pointers (Not References)
#

C was designed for low-level systems programming, where direct memory manipulation is essential. Higher-level abstractions like references:

  • Add complexity
  • Obscure low-level semantics
  • Are unnecessary for system-level tasks

C++ added references later, mainly to:

  • Support operator overloading
  • Improve syntactic convenience
  • Enable more expressive abstractions

When to Use References vs Pointers
#

A practical guideline:

✔️ Use a reference when:
#

  • The object must not be null
  • You need clean, expressive code
  • You want the callee to modify the caller’s variable

✔️ Use a pointer when:
#

  • You may need to pass nullptr
  • Rebinding is needed
  • Pointer arithmetic is required
  • You work with dynamic memory

Summary
#

  • C++ references compile to the same assembly as pointers.
  • References are implemented as constant pointers.
  • Their restrictions make them safer and clearer for many use cases.
  • Pointers remain essential for low-level control and flexibility.

Understanding these details gives you deeper insight into how C++ behaves at the machine level—and helps you choose the right tool for the job.

Related

C/C++循环结构:do{} while()和while() do{}的区别
·94 words·1 min
程序 C C++
NULL vs nullptr in Modern C++: What Developers Should Know
·537 words·3 mins
C C++ NULL Nullptr
A Practical Guide to #pragma and Its Powerful Uses in C/C++
·500 words·3 mins
C++ Pragma Compiler Directives C Programming