C++ do references occupy memory
Asked Answered
P

3

6

I have read that reference is just an alias to a variable existing in the symbol table. Consider the following code

int main()
{
    int y = 6;
    int &z = y;
    int k = 43;
    test(2,y,5,78);
    cout << &y << "\n";
    cout << &z << "\n";
    cout << &k << "\n";
}

void test(int a,int & x, int g, int h)
{
    cout << &a << "\n";
    cout << &x << "\n";
    cout << &g << "\n";
    cout << &h << "\n";
}

For the output I get

0039F740
0039F848
0039F748
0039F74C
0039F848
0039F848
0039F830

If reference does not occupy memory in the stack, why is the memory being offset. Eg. In the function test, local variable a is at 0039F740 but g is at 0039F748. Shouldn't g be at 0039F744?

Could someone please explain it in depth?

Please answered 14/9, 2016 at 2:37 Comment(1)
It's unspecified whether a reference requires storage. The compiler writer will make a decision about how to implement the reference in any situationZorine
A
4

Your function has four parameters.

Each parameter must be passed to the function.

The fact that one of the parameters is a reference does not change this basic fact. The additional space you see is the reference parameter to the function.

In this context, the reference is really just a pointer in disguise. When you have a reference in a local scope referencing to an object in the local scope, most C++ compilers will, indeed, optimize it away so that the reference does not take up any actual memory.

But a function call is an entirely new ball game. The function expects to receive a reference to some object. The function cannot know telepathically what is being passed to it as a reference. Whatever is calling the function is responsible for supplying the reference parameter. It goes without saying that a few bytes will be needed to pass along that information, namely the address of an object that's passed as a reference (did I mention something about pointers, recently?)

It is certainly possible that if the function was declared with static scope (no external linkage), and a sufficiently aggressive optimization level is selected for compilation, your C++ compiler will inline the function call, and be able to optimize the reference parameter away.

But declaring a function with external linkage generally results in the compiler not bothering to attempt to inline the function call. It will proceed and generate a full-blown, standalone function, that expects to have each and every parameter it is entitled to.

To answer your question in a more general way: the C++ standard does not require that references should occupy memory, but it does not require that they should not. The C++ compiler is free to compile the code in any way, as long as the results are correct, and what they are expected to be. If, in a particular situation, a C++ compiler figures out how to optimize away a reference so that it does not actually "exist" as a discrete object of its own, it is free to do so. But it is not required to do that.

Absurd answered 14/9, 2016 at 2:50 Comment(6)
Does that mean the local variable z does not take up any actual memory? And also why is the local variable k at 0039F830?Please
It may or may not, depending on what your compiler does, as I explained in my answer. Additionally, the compiler is not required to assign any particular memory address to any variable. The compiler might choose to store the local objects that way due to hardware-related alignment reasons, for example.Absurd
So is it safe to assume that underneath the hood, when passing by reference, you are still pushing the address of reference onto the stack?Please
@Please What part of "a compiler compiler is free to make its own choice for a given situation" do you not understand? Given that either option is possible - you should not be making any assumptions! Furthermore, why are you so hung up about being able to make this assumption in the first place? .... What's your real question?Echelon
@CraigYoung Yes I understand that the compiler is free to make its own choice whether a reference will use memory or not. But what I am asking now is that when you call a function with a reference as its argument, will that be stored in either memory/register or use up nothing at all. If this is also dependent on the compiler then it goes against what I've learnt about the calling conventions.Please
@TFK: Compilers are certainly allowed to violate calling conventions, including the outright removal of a call (which is called inlining).Constructive
A
2

References are more complicated than "aliases to something else in the symbol table". That definition, in fact, often doesn't even apply. For instance, a reference parameter cannot just be aliased to "something else in the symbol table", because that would prevent the function from being called with more than one distinct argument values.

The standard doesn't say how you should do it, but the typical implementation of references is to just use pointers. If you have an int& x, then x returns *(pointer) and &x returns (pointer). Pointers do occupy memory, but no well-defined C++ operation will transpire the storage location of the pointer that backs a reference.

Do note that unless you need to get the address of an object with automatic storage ("on the stack"), the compiler isn't required to actually put it on the stack. It could live entirely in registers, or it could be entirely optimized away. For instance, with this function:

int foo(int a, int b) { return a + b; }

On x86_64 with the System V calling convention, a is passed in the rdi register, b is passed in the rsi register, the result is computed in rax, and the function doesn't need to touch the stack for any of its values.

Arvad answered 14/9, 2016 at 3:0 Comment(0)
Y
0

I think it has do with the fact that base pointer changes

if the compiler just wants to implement them as aliases then, whenever the function uses the reference we need to replace it the original address but as this reference comes form a function down in the stack this address will be of form (Basepointer - offset). but on entry in this new function (i.e test) we change the BP at the start so its not possible anymore so we need to implement this reference a pointer and that takes up memory.

Yellowish answered 11/7, 2023 at 11:10 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.