Reputation: 151
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
Reputation: 241721
Compare and contrast:
struct container {
long double& dbl;
};
std::cout << sizeof(container::dbl) << '\n';
std::cout << sizeof(container) << '\n';
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
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
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