Re: Arrays of Objects
Francis Glassborow wrote:
Tjark Weber wrote:
Hi,
I shamelessly took the following example from the "C++ FQA" that was
posted earlier, and I would assume it's well-known in this group.
class A { public: int a; };
class B : public A { public: int b; };
A * p = new B[10];
p[5].a = 1;
On my system, memory for integers 0..19 is allocated, and integer 5 is
assigned the value 1 (rather than integer ... umm ... 10, I guess).
What does the C++ standard have to say about this code? Does it
invoke undefined behavior? Is the behavior completely specified, and
bound to be as on my system? Or could the compiler be smart enough to
"get this right"?
I do not understand what you are claiming. In the above example "new
B[10]" creates a dynamic array of 10 pairs of ints (stupid, because a
vector is the preferred way to create dynamic arrays). The first of each
pair is .a and the second is .b. Arrays are laid out in contiguous
memory. The standard strictly speaking allows padding in instances of a
class but it would be a pretty silly implementation that had any padding
in B (well not quite because debugging implementations sometimes add
padding as locations where they can flag lifetime exhaustion etc.)
B[10] contains ten contiguous instances of B (indexed from 0 to 9). p[5]
says find the instance indexed as 5 (the sixth in common speak) and now
set the 'a' member (inherited from the A class) to 1.
Now what is there for the compiler to get wrong (unless it is hopelessly
broken)
I was obviously not looking closely enough at the code. On looking again
I see that the pointer returned by new is captured by a pointer for a
base type. This is fine for single objects and you get polymorphic
behaviour but it is a big no-no for arrays. The compiler will use the
static (declared type) of the pointer for determining the step size when
stepping through the array. But the static type is pointer to A and the
sizeof A is the wrong size for an array of B.
This results in undefined behaviour (actually the behaviour is still
undefined even if the derived type does not include extra data, but you
usually get away with it in that case.
--
Note that robinton.demon.co.uk addresses are no longer valid.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]