Does reference variable/reference parameter store address?


I know that reference is an alias to a variable but i read somewhere online that reference store address of the variable it refers to. Kind of confused right now.






https://www.google.com/amp/s/www.geeksforgeeks.org/pointers-vs-references-cpp/amp/

"References: A reference variable is an alias, that is, another name for an already existing variable. A reference, like a pointer, is also implemented by storing the address of an object.
A reference can be thought of as a constant pointer (not to be confused with a pointer to a constant value!) with automatic indirection, i.e., the compiler will apply the * operator for you. "


https://www3.ntu.edu.sg/home/ehchua/programming/cpp/cp4_PointerReference.html
"
2.2 How References Work?
A reference works as a pointer. A reference is declared as an alias of a variable. It stores the address of the variable, as illustrated:"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// the differences between a reference and a pointer

#include <iostream>

int main()
{
   int a = 12;

   std::cout << "a:   " << a << '\n';
   std::cout << "&a:  " << &a << "\n\n";

   int* pa = &a;

   std::cout << "pa:  " << pa << '\n';
   std::cout << "*pa: " << *pa << '\n';
   std::cout << "&pa: " << &pa << "\n\n";

   int& ra = a;

   std::cout << "ra:: " << ra << '\n';
   std::cout << "&ra: " << &ra << '\n';
}
a:   12
&a:  00000046688FFA78

pa:  00000046688FFA78
*pa: 12
&pa: 00000046688FFA70

ra:: 12
&ra: 00000046688FFA78

References don't have an address in storage, a reference variable is not a separate entity from the object being referenced. References are simply an alias to the referenced object, and can never be null. It must always have a valid object.

No memory is used for a reference.

If you sizeof a reference you get the memory of the referred (aliased) object, not the reference.

Pointers and the objected being pointed to are separate entities. Pointers use extra memory.

A pointer's sizeof can be different from the size of of the object being pointed to.

Think of references as a "nick-name" for a variable. Harold Thomas Worthington IV with a nick-name of Skippy is the same person. Calling someone who doesn't exist as Skippy is meaningless.
Well, if you pass an object by reference into function, and if we assume that the function call does not get inlined, then somehow the reference needs to be stored, so that the function being called can pick it up – either on the stack or in a register (depending on how the "calling convention" passes the parameter). And what gets stored there is nothing but the address of the object! So I think we can say that, technically, references are implemented just like pointers – they pass the address of the object rather than a "copy" of that object.

Sure, within a function, or if the function call gets inlined, there is no need to actually "store" the reference (i.e. address of the object) anywhere, because we can simply access the referenced object "directly"; the reference then acts as an "alias" for the object. But the same would be true when working with pointers, I believe.

See also:
https://stackoverflow.com/a/3954803/19369426
Last edited on
While it is true that a reference: is another name for a variable; that may not be changed to reference another variable; the address of a reference may not be taken. That is a suitable concept to remember, but there is more to it in how it is implemented.

In the past I mentioned that a reference is like a const pointer wrapped in some Template Meta Programming (TMP) code. No one seems to have disagreed with me, so it seems there may be some truth to what I said because normally any incorrect information is jumped on straight away by someone.

I haven't found any direct evidence in a header file that the compiler employs a const pointer to implement a reference, but I am not sure if there is any other logical way of doing it to meet the requirements. The TMP code below directly uses the reference ampersand in it's types, so that tells me that the low level implementation will be in the depths of the compiler itself - maybe in the lexer?

I discovered the TMP part by looking at the type traits header on my system. I know that the implementation is not specified in the standards, and compiler vendors may implement it any way they choose, so long as it works. On my system the add_lvalue_reference inherits from various TMP structs to make it a reference type:

689
690
691
692
693
694
695
696
697
698
699
700
 // Utility to detect referenceable types ([defns.referenceable]).

  template<typename _Tp, typename = void> 
    struct __is_referenceable
    : public false_type
    { };    

  template<typename _Tp>
    struct __is_referenceable<_Tp, __void_t<_Tp&>>
    : public true_type
    { };    
  /// @endcond 


1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652

template<typename _Tp, bool = __is_referenceable<_Tp>::value>
    struct __add_lvalue_reference_helper
    { typedef _Tp   type; };

  template<typename _Tp>
    struct __add_lvalue_reference_helper<_Tp, true>
    { typedef _Tp&   type; };

  /// add_lvalue_reference
  template<typename _Tp>
    struct add_lvalue_reference
    : public __add_lvalue_reference_helper<_Tp>
    { };


A similar thing happens for rvalue references.
As mentioned, in the language, references have no size and no address, they are just additional names for objects. They are not related to pointers (which have a size and an address and a lot of other special properties)

In the implementation, what is passed to a function taking a reference parameter is specified in a separate standard, the ABI. The two most popular C++ ABIs (the one used by Windows x64 and the one used by Linux and other non-Windows x64) both use addresses in this case; on Windows, non-inlined f(int&) takes an address in CPU register RCX. On non-Windos, non-inlined f(int&) takes an address in CPU register %rdi.
Last edited on
Topic archived. No new replies allowed.