Al227
Al227

Reputation: 151

Reference — does sizeof return the real memory size?

I know this question has probably been asked in many different ways, but I'm adding my own because this is still unclear for me.

Consider this code:

long double q = 1.2;
long double &p = q;
cout << sizeof(p) << endl;`

long double is 12 bytes on my machine, and the output of the code is as expected 12 because as the standard says:

When applied to a reference or a reference type, the result is the size of the referenced type. (ISO C++ $5.3.3/2)

But as you most likely all know, references implementation is free, and thus, as the standard says again:

It is unspecified whether or not a reference requires storage (3.7).

So it seems that tomorrow I can come up with my own reference implementation that takes 200 bytes and make sure that the sizeof operator returns the right object size (instead of returning what would be the true implementation size of my reference)

So my question is actually extremely simple:

Can we rely on the sizeof operator to return the real memory occupation of a class when it contains, specifically, reference members?

Upvotes: 2

Views: 423

Answers (3)

rici
rici

Reputation: 241721

Compare and contrast:

struct container {
  long double& dbl;
};

std::cout << sizeof(container::dbl) << '\n';
std::cout << sizeof(container)      << '\n';

(Live on ideone)

One line tells you the size of a referred-to object. The other tells you the size of the structure containing the reference.

That behaviour is not by chance. It's defined by the standard and yes, you can rely on it.

There seems to be an assumption behind this question that the behaviour of the sizeof operator with a reference or reference type is somehow arbitrary and conventional. That is not the case; it falls out of the same logic that generally applies to references.

If I have

long double dbl;

then any use of dbl in its scope is an lvalue, which is to say a reference. That is necessary in order for it to be possible to assign a value to dbl. So the type of dbl (as revealed, for example, by decltype(dbl)) is long double&, not long double.

It would be ridiculous for sizeof(dbl) to return the size of the reference itself rather than the size of the referenced object.

Once you put the reference into a structure, you have a completely different beast. As part of an object, the reference occupies space, which cannot be optimized away unless the entire object containing it can be optimized away.

Upvotes: 6

Jonathan Wakely
Jonathan Wakely

Reputation: 171263

struct S {
    long double& d;
};

static_assert(sizeof(S::d) == sizeof(long double));
static_assert(sizeof(S) != sizeof(S::d));  // true on most platforms

The compiler is smart enough to know the size of S, it doesn't get confused and think it is sizeof(S::d) because that would be stupid.

Upvotes: 0

PiotrNycz
PiotrNycz

Reputation: 24402

If you question if you can rely on sizeof of the following type:

struct A
{
   int& r;
};

Then yes - you can rely on sizeof in structs containing references.

E.g. this code is safe:

   char* buffer = new char[sizeof(A)];
   int value;
   A* valueRef = new (buffer) A{value};

You have enough bytes in buffer to store A object.

Upvotes: 0

Related Questions