1

Consider the following program:

#include <stdio.h>

struct A
{
    int x;
};

int main()
{
    printf("%d\n", sizeof(A));
    return 0;
}

As expected, this program prints the number 4 because the integer in A uses 4 bytes. However, let's change the program into this:

#include <stdio.h>

struct A
{
    int  x;
    int& r = x;
};

int main()
{
    printf("%d\n", sizeof(A));
    return 0;
}

Now the program prints the number 16.

I've always been told that references in C++ works like an alias, as in offering another name for the same variable. Thus, I expected the struct to still have a size of 4 bytes since the reference r is just another name for x, which will get replaced by the actual variable x when compiled.

Obviusly, this doesn't seem to be the case. Instead, it seems that the reference takes up just as much memory as a pointer would do. If we change int& r = x; into int* p = &x; the program will also print 16. From my point of view this doesn't make any sense because why have references if they take up memory just as pointers do, then we might just use pointers instead.

I did one more test program with the following code:

#include <stdio.h>

struct A
{
    int  x;
    int  y;
    int  z;
    int& X = x;
    int& Y = y;
    int& Z = z;
};

int main()
{
    printf("%d\n", sizeof(A));
    return 0;
}

And the program above prints 40. That seems very weird in my eyes since the 3 integers should take up 4 bytes each, making it 12 bytes in total, and leaving 28 bytes left for the references. But 28 is not evenly divisible by 3.

I've compiled this with Visual Studio 2015 in x64 configuration.

So my question is: Have I done something wrong here or why does a C++ reference use up memory in a struct?

  • @Baum mit Augen: So why does a reference use up memory in a struct? What's the point of having references if they're basically equal to a pointer except the pointer arithmetic? And why does 3 integers + 3 references take up 40 bytes and not 36 bytes? Since these questions are still unanswered, I honestly don't think this is a duplicate question. – fighting_falcon93 Jul 01 '18 at 20:11
  • 1) How does it matter whether it's in a struct? 2) Added two dupe targets for that, because hey, why not and 3) is exactly the same question as one of the dupes. – Baum mit Augen Jul 01 '18 at 20:15
  • Unless the compiler optimizes away the reference, references are pointers in disguise. Any compiler will produce the exact same assembler for a reference as for a pointer, unless the C++ code touches on one of the special guarantees for references. C++ enthusiastic language lawyers may disagree with me on this, but this is how references are implemented on a physical level. If you don't believe me, just compile these two functions with `gcc -S -Os` and compare the output: `int& p2r(int*a) {return *a;}` and `int* r2p(int&a) {return &a;}` Both compile to a noop that simply returns its argument. – cmaster - reinstate monica Jul 01 '18 at 20:19
  • @Baum mit Augen: 1) Because it may mess up potential use of `memcpy`, `memset` etc. Let's say for example that we have another struct `B` with members `int a; int b; int c;` (no references), and with the assumption that references use up no memory, one might try to use `memcpy` to move the values from struct `B` to struct `A`, which will paste bytes outside `B` because it's smaller. 2) Sorry but both those questions are more about the `sizeof` rather than actually explaining the point of references. Note that I'm not asking about the *differences*, but rather the point of having references. – fighting_falcon93 Jul 01 '18 at 20:29
  • @cmaster Thank you. But sadly I still don't understand the point in having references if they're used like pointers. Then we might aswell use pointers instead, right? I thought the hole point of using references was to bypass the hole process of having to spend extra instructions on de-referencing the pointer? – fighting_falcon93 Jul 01 '18 at 20:33
  • @fighting_falcon93 That is not the point of references, as you could have learned by actually reading the answers to the dupes. I disagree with your objections, so I'll leave the question closed. If you edit your question to explain why it is not a duplicate, the community will review my decision. – Baum mit Augen Jul 01 '18 at 20:36
  • @Baum mit Augen: The first dupe explains what happens when you take `sizeof` from a reference, but that's not what I asked. The second dupe explains why `sizeof` does not always return the size of all combined members, but once again that's not what I asked. The third dupe explains the difference between pointers and references, but I never asked for the difference between them. The fourth dupe explains when to use references and when to use pointers, once again not quite what I asked for. I still wonder why references exist if they take up memory and need to be dereferenced just like pointers – fighting_falcon93 Jul 01 '18 at 20:47
  • 1
    The missing 4 bytes is probably padding to 64 bit align the reference that is unfortunately being implemented as a pointer. we have 32 bit int, 32 bit int, 32 bit int. That's 12 bytes. A 64 bit address cannot start (or will have sub-optimal performance) until the 16th byte. – user4581301 Jul 01 '18 at 21:01
  • 1
    As an aside, I don't think you want to `memcpy` or `memset` one of these structures. You aren't allowed to re-point a reference and `memcpy` and `memset` will try to do exactly that. A case of works here, but if a smarter compiler handles the reference differently, you're SOL. – user4581301 Jul 01 '18 at 21:05
  • @user4581301 I fully agree considering how references seem to work. I've always thought that references was just a name, so that `int& r = x;` would be just a compiler instruction and not take up actual bytes in the struct. If it where that way, `memcpy` would work fine. But considering how it seems to work, I fully agree with you. – fighting_falcon93 Jul 01 '18 at 21:07
  • And thanks to whoever that downvoted me. Taking your time to write a question just to get it marked as duplicate by similiar questions and then lose reputation. – fighting_falcon93 Jul 01 '18 at 21:11
  • 2
    @fighting_falcon93 "I thought the hole point of using references was to bypass the hole process of having to spend extra instructions on de-referencing the pointer?" No. Definitely not. References don't save anything in terms of performance. Afaik, the point was to provide a "safe" alternative to pointers. That was done by providing something that's pointers in disguise (because pointers **are** useful), forbidding them to be null, and some other stuff that was seen as nasty. Obviously that plan didn't fully deliver on its goals, as you can still get null and dangling references... – cmaster - reinstate monica Jul 01 '18 at 21:22
  • 1
    Btw. while the first two listed duplicates are really low quality and don't really qualify as duplicates in my eyes, the third one seems worth a read. – cmaster - reinstate monica Jul 01 '18 at 21:27
  • Reference can be just a name and often it is, but structures are passed around and used in a variety of different circumstances and it better have the same size and shape in all of those circumstances. If a compiler can prove that the references can always just be a name, groovy, but stuff that can straddle translation units is stuck supporting the lowest common denominator. Here that's reference-as-stored-address. But it COULD be just a name. – user4581301 Jul 01 '18 at 21:29
  • @cmaster Yep, I'm reading it right now. I understand the differences between the 2, but in my eyes they're so similiar that I don't understand why they decided to make it 2 different entities. But oh well, it is as it is :P – fighting_falcon93 Jul 01 '18 at 21:32

0 Answers0