Code not valid.
A size of 0 is invalid, both for classes and arrays. The C++ standard says:
Sizeof [expr.sizeof]
[...] The size of a most derived class shall be greater than zero [...]
and
Arrays [dcl.array]
In a declaration T D where D has the form
D1 [ constant-expressionopt] attribute-specifier-seqopt
[...] If the constant-expression (5.19) is present,
it shall be an integral constant expression and its value shall be greater than zero [...]
Why compiles? Compiler extension!
If you turn on -pedantic
with g++, you will receive the following warning (or error with pedantic-errors
):
ISO C++ forbids zero-size array ‘n’
so your program is basically not valid, but can be compiled by means of a compiler extension to the C++ standard (unless you turn this extension off).
Note: Even though your compiler can report 0
for the class
, it won't do so for any instance (a.k.a. object) of that class
:
#include <iostream>
class Boom {
int n[0];
};
int main() {
std::cout << sizeof(Boom) << '\n'; // prints 0
std::cout << sizeof(Boom()) << '\n'; // prints 1
}
Having objects of size-0 would go simply too far off the standard.
Citation by Stroustroup:
Why is the size of an empty class not zero?
To ensure that the addresses of two different objects will be different. For the same reason, "new" always returns pointers to distinct objects. Consider:
class Empty { };
void f()
{
Empty a, b;
if (&a == &b) cout << "impossible: report error to compiler supplier";
Empty* p1 = new Empty;
Empty* p2 = new Empty;
if (p1 == p2) cout << "impossible: report error to compiler supplier";
}
There is an interesting rule that says that an empty base class need not be represented by a separate byte:
struct X : Empty {
int a;
// ...
};
void f(X* p)
{
void* p1 = p;
void* p2 = &p->a;
if (p1 == p2) cout << "nice: good optimizer";
}
This optimization is safe and can be most useful. It allows a programmer to use empty classes to represent very simple concepts without overhead. Some current compilers provide this "empty base class optimization".