3

I have been told that references, when they are data members of classes, they occupy memory since they will be transformed into constant pointers by the compiler. Why is that? Like why does the compiler(I know that it is implementation-specific in general) make a reference a pointer when they are part of a class, as opposed to when they are a temporary variable? So in this code:

class A{
public:
  A(int &refval):m_ref(refval){};
private:
  int &m_ref;
}

m_ref will be treated as a constant pointer(i.e. they do occupy memory).

However, in this code:

void func(int &a){
  int &a_ref = a;
}

the compiler just replaces the reference with the actual variable(i.e. they do not occupy memory).

So to simplify a little, my question basically is: What makes it more meaningful to make references into constant pointers when they are data members than when they are temporary variables?

  • 7
    You receive an arbitrary instance of that class as a function parameter. How are you going to know what the reference refers to if you didn't store it in the instance? – Quentin Jun 28 '17 at 12:29
  • As far as I know, a reference is defined to be an alias, it is not guaranteed to take memory (this also explains why you can't have a pointer to a reference). If the compiler can get away with not using memory for that reference while maintaining the correct behavior it is free to do so. In the case of the class member it obviously has to use some memory. – Borgleader Jun 28 '17 at 12:29
  • @Borgleader - it is also not guaranteed to take no memory. – Peter Jun 28 '17 at 12:32
  • @Peter Did I imply otherwise? – Borgleader Jun 28 '17 at 12:36
  • 1
    @Borgleader - you didn't, but you skirted around that a little, which makes it easier for casual or inexperiencedreaders to misinterpret. So I simply said it more directly. – Peter Jun 28 '17 at 12:43
  • @Borgleader why does it **obviously** has to use memory(i.e. make the reference into a pointer)? –  Jun 28 '17 at 13:06
  • 2
    If you can't *deduce* from the code what your reference refers to, you have to *store* it somewhere. There's really no other way to compile a program. – n. m. could be an AI Jun 28 '17 at 13:12
  • @Thu A reference taking memory is the default case if you will. How do you expect each instance of A to be able to remember which int `a_ref` is an alias of without taking any memory? – Borgleader Jun 28 '17 at 13:14
  • @n.m. so cna you say that by making the reference to a pointer, you sort of allow them to left uninitialized, like a_ref are, I guess? –  Jun 28 '17 at 13:32
  • @Borgleader but why isn't it taking memory in the second code example then? I cannot expect it to remember anything there either, can I? –  Jun 28 '17 at 13:35
  • @Thu Of course you can, in the second example `a_ref` is completely useless because it is exactly the same thing as `a` so using `a_ref` is like using `a` they both alias to the same object. – Borgleader Jun 28 '17 at 13:36
  • @Borgleader so is it because of that the reference is being initialized by the constructor/using a parameter or? That it is treated as a const pointer. –  Jun 28 '17 at 13:40
  • "you sort of allow them to left uninitialized" I have no idea what you mean by that. – n. m. could be an AI Jun 28 '17 at 13:42
  • Not really, it has to do with the kinds of assumptions the compiler can make. In the second example `a_ref` is redundant, but in the first it can be initialized in one scope and used in another scope, at which point the compiler may not be able to reason about where the reference came from. If the compiler can *without a doubt* reason about what a reference points to it may get away without using memory, generally speaking for a member variable you cannot do that. – Borgleader Jun 28 '17 at 13:44
  • @n.m. what I mean is that... References cannot be left uninitialized but pointers can and since a_ref is left uninitialized, it would make sense to transform that reference to a pointer, at least to me, in order to allow the reference to wait for the assignment to happen after it is declared.. –  Jun 28 '17 at 13:50
  • [Consider this example](http://coliru.stacked-crooked.com/a/2899849756ac620c) this may help explain why the member needs to use memory, if not, I dont know what to tell you. – Borgleader Jun 28 '17 at 13:57
  • @Borgleader nice explanation. So it is basically because that when used as a data member it is difficult for the compiler to keep tracking of what the reference is bound to? or am I still misunderstanding something? I get the last part of your comment though :) Thanks for letting me steal some of your time :)) –  Jun 28 '17 at 13:57
  • I stil have no idea what you are talking about. A reference is not a pointer and a compiler does not transform one to another. A compiler can implement references and pointers using similar techniques. This doesn't change the nature of references, which are still not pointers regardless of implementation methods.. That's all there is to it. – n. m. could be an AI Jun 28 '17 at 13:58
  • @Borgleader I just saw that you posted an example. So you said this "// while this may seem redundant, consider the print call, how could it refer to the right int without using some memory?", couldn't it just replace the reference with the address of the int? :/ –  Jun 28 '17 at 14:07
  • I dont know what you mean. – Borgleader Jun 28 '17 at 14:11
  • @Borgleader when you said " while this may seem redundant, consider the print call, how could it refer to the right int without using some memory?", couldn't the compiler simply replace the reference with the address of the integer instead of making the reference into a pointer and then make that pointer point to the address of the integer? I know that I am maybe a little too confused. –  Jun 28 '17 at 14:14
  • @Borgleader or would that simply not be possible? –  Jun 28 '17 at 17:39
  • As I've said before, I don't know how else to explain it. – Borgleader Jun 28 '17 at 18:03

3 Answers3

5

The C++ standard only defines the semantics of a reference, not how they are actually implemented. So all answers to this question are compiler-specific. A (silly, but compliant) compiler might choose to store all references on the hard-disk. It's just that it proved to be the most convenient/efficient to store a reference as a constant pointer for class members, and replace the occurence of the reference with the actual thing where possible.


As an example for a situation where it is impossible for the compiler to decide at compile time to which object a reference is bound, consider this:

#include <iostream>

bool func() {
    int i;
    std::cin >> i;
    return i > 5;
}

int main() {
    int a = 3, b = 4;
    int& r = func() ? a : b;
    std::cout << r;
}

So in general a program has to store some information about references at runtime, and sometimes, for special cases, it can prove at compile time what a reference is bound to.

alain
  • 11,939
  • 2
  • 31
  • 51
  • Thank you. But why exactly does the reference have to take memory in your example? –  Jun 30 '17 at 15:09
  • When the program reaches the last line `std::cout << r`, it needs to remember if r refers to a or to b. It can't remember it without some kind of "memory" ("memory" in a very broad sense, it could also be a register for example). – alain Jun 30 '17 at 16:30
  • Well okay but take a look at this https://stackoverflow.com/a/1179994/8221510 where he says "make a note in the symbol table that j is now an alias for i". Couldn't the compiler just do this in your code example? –  Jun 30 '17 at 16:34
  • and thereby remember it, or am I misunderstanding something? Thanks for letting me take some of your time :) –  Jun 30 '17 at 16:46
  • 1
    No, the compiler can't do that with my specially crafted "evil" example, because how would it know in advance what the user enters? (Look at `func()`, the return value depends on what the user enters) – alain Jun 30 '17 at 22:10
0

The reference (or pointer) has to be stored in memory somewhere, so why not store it along with the rest of the class?

Even with your example, the parameter a (int &a) is stored in memory (probably on the stack), then a_ref doesn't use any more memory, it's just an alias, but there is memory used by a.

Neil
  • 11,059
  • 3
  • 31
  • 56
0

Imagine that a class is just a user defined data type. You need to have something which can lead you to the actual thing that you are referencing. Using the actual value in the second case is more about the compiler and his work to optimize your code. A reference should be an alias to some variable and why should this alias use memory when it could be optimized to be taken directly from the stack.

Petar Velev
  • 2,305
  • 12
  • 24