<p>I would not be surprised if C++ style <code>int &amp;y = x;</code> was no more than <code>int *y = &amp;x;</code> behind the scenes and every use of <code>y</code> was implicitly <code>*y</code>, and that this would this incur the computational expense of pointer indirection. And since the pointer is being stored anyway, there would be no memory-saving benefits here.</p>
<p>However, would implementing C++ style references in a manner that was direct, and more efficient than just using pointers behind the scenes, such as <code>y</code> accessing <code>x</code> on the stack directly the same way simply writing <code>x</code> does (besides a preprocessor macro) be possible? The same way <code>x</code> refers to a certain register at translation time, <code>y</code> could be made to refer to the same register. If there is a <code>struct</code> and a reference is declared to point to the member, could the reference just be made to refer to the register member at translation time without pointers? What would implementing this take?</p>

<implementation><c++><pointers><references>
How are C++ style references implemented behind the scenes? Could they be implemented without pointers?
CC BY-SA 4.0
2023-06-07T00:41:14.770Z
is compiler inlining a consideration here? Or is this question ruling out compiler inlining?
starball
CC BY-SA 4.0
2024-12-27T13:25:45.333Z
Well, `int *const y = &x;`.
user3840170
<p>I believe such optimizations are carried out at a later stage of compilation. The compiler back-end, when analyzing the function's IR, is able to notice that a reference is only used within the function, and then replace its uses with the underlying variable directly. The same thing can be automatically applied to pointers as well. It's essentially just a slight modification of the copy propagation algorithm</p>

CC BY-SA 4.0
2023-06-07T07:07:55.067Z
2023-06-07T07:07:55.067Z
abel1502
<p>From an implementation perspective, there is one very important difference between a pointer and a reference in C++: references cannot be null.</p>
<p>This is undefined behaviour:</p>
<pre class="lang-cpp prettyprint-override"><code>int* px = nullptr;
int &amp;rx = *px;
</code></pre>
<p>This doesn't make a difference except in one specific scenario: casting in the presence of multiple inheritance.</p>
<p>Consider this:</p>
<pre class="lang-cpp prettyprint-override"><code>struct base1 {
    uint64_t member1;
};

struct base2 {
    uint64_t member2;
};

struct derived : public base1, base2 {
};
</code></pre>
<p>What code should this function compile to?</p>
<pre class="lang-cpp prettyprint-override"><code>base2&amp; cast_from_derived_to_base2_ref(derived&amp; pd)
{
    return (base2&amp;)pd;
}
</code></pre>
<p>If you said &quot;basically add 8&quot;, you would be correct. Clang 16.0.0 on x64 at <code>-O2</code> generates this code:</p>
<pre><code>cast_from_derived_to_base2_ref(derived&amp;):
        lea     rax, [rdi + 8]
        ret
</code></pre>
<p>Now, what code should this function compile to?</p>
<pre class="lang-cpp prettyprint-override"><code>base2* cast_from_derived_to_base2_ptr(derived* pd)
{
    return (base2*)pd;
}
</code></pre>
<p>If you said &quot;the same code&quot;, you would be wrong. It would give an incorrect answer if <code>pd</code> were a null pointer; in that case, this function should also return a null pointer.</p>
<p>This is the code that Clang 16.0.0 generates:</p>
<pre><code>cast_from_derived_to_base2_ptr(derived*):
        lea     rax, [rdi + 8]
        test    rdi, rdi
        cmove   rax, rdi
        ret
</code></pre>
<p>Of course, there are also high-level semantic differences (references are immutable, for example), but this is the key difference in implementation.</p>
<p>Having said all that, implementing a reference as a value rather than a pointer would be an optimisation. The main barrier would be escape analysis; the compiler would have to be convinced that the location referred to isn't visible from outside the current function (e.g. another thread).</p>

CC BY-SA 4.0
2023-06-07T06:45:51.287Z
2023-06-07T08:17:07.240Z
2023-06-07T08:17:07.240Z
Pseudonym
# How are C++ style references implemented behind the scenes? Could they be implemented without pointers?
Posted by: username_0 on 2023-06-07
I would not be surprised if C++ style `int &y = x;` was no more than `int *y = &x` behind the scenes and every use of `y` was implicitly `*y`, and that this would this incur the computational expense of pointer indirection. And since the pointer is being stored anyway, there would be no memory-saving benefits here.

However, would implementing C++ style references in a manner that was direct, and more efficient than just using pointers behind the scenes, such as `y` accessing `x` on the stack directly the same way simply writing `x` does (besides a preprocessor macro) be possible? The same way `x` refers to a certain register at translation time, `y` could be made to refer to the same register. If there is a `struct` and a reference is declared to point to the member, could the reference just be made to refer to the register member at translation time without pointers? What would implementing this take?
**Tags:** implementation c++ pointers references
> **Comments:**
> **username_1**: is compiler inlining a consideration here? Or is this question ruling out compiler inlining?  
> **username_2**: Well, `int *const y = &x;`.  
---
## 2 answers
### Answer by username_4 on 2023-06-07. Score: 11 | Accepted answer
From an implementation perspective, there is one very important difference between a pointer and a reference in C++: references cannot be null.
This is undefined behaviour:
int* px = nullptr;
int ℞ = *px;

This doesn't make a difference except in one specific scenario: casting in the presence of multiple inheritance.
Consider this:
struct base1 {
    uint64_t member1;
};

struct base2 {
    uint64_t member2;
};

struct derived : public base1, base2 {
};

What code should this function compile to?
base2& cast_from_derived_to_base2_ref(derived& pd)
{
    return (base2&)pd;
}

If you said "basically add 8", you would be correct. Clang 16.0.0 on x64 at -O2 generates this code:
cast_from_derived_to_base2_ref(derived&):
        lea     rax, [rdi + 8]
        ret

Now, what code should this function compile to?
base2* cast_from_derived_to_base2_ptr(derived* pd)
{
    return (base2*)pd;
}

If you said "the same code", you would be wrong. It would give an incorrect answer if pd were a null pointer; in that case, this function should also return a null pointer.
This is the code that Clang 16.0.0 generates:
cast_from_derived_to_base2_ptr(derived*):
        lea     rax, [rdi + 8]
        test    rdi, rdi
        cmove   rax, rdi
        ret

Of course, there are also high-level semantic differences (references are immutable, for example), but this is the key difference in implementation.
Having said all that, implementing a reference as a value rather than a pointer would be an optimisation. The main barrier would be escape analysis; the compiler would have to be convinced that the location referred to isn't visible from outside the current function (e.g. another thread).
---
### Answer by username_3 on 2023-06-07. Score: 4
I believe such optimizations are carried out at a later stage of compilation. The compiler back-end, when analyzing the function's IR, is able to notice that a reference is only used within the function, and then replace its uses with the underlying variable directly. The same thing can be automatically applied to pointers as well. It's essentially just a slight modification of the copy propagation algorithm
---
