This answer by CB Bailey is more accurate from the point of view of language specification. It more clearly explains why accessing shapes[i]
is undefined behavior. That answer is quoted below with the pointer variable changed to shapes
, Shape
as the base class and Rectangle
as the derived class (instead of p
, Base
and Derived
from that question).
If you look at the expression shapes[1]
, shapes
is a Shape* (Shape
is > a completely-defined type) and 1 is an int, so according to ISO/IEC
14882:2003 5.2.1 [expr.sub] this expression is valid and identical to
*((shapes)+(1))
.
Thus, accessing shapes[i]
is not ill-formed. However, it is undefined as explained below.
From 5.7 [expr.add] / 5, when an integer is added to a pointer, the
result is only well defined when the pointer points to an element of
an array object and the result of the pointer arithmetic also points
the an element of that array object or one past the end of the array.
shapes
, however, does not point to an element of an array object, it
points at the base class sub-object of a Derived object. It is the
Rectangle
object that is an array member, not the Shape
sub-object.
Note that under 5.7 / 4, for the purposes of the addition operator,
the Shape
sub-object can be treated as an array of size one, so
technically you can form the address shapes + 1
, but as a "one past the
last element" pointer, it doesn't point at a Shape
object and
attempting to read from or write to it will cause undefined behavior.
These paragraphs give a very good idea of how the expression shapes[i]
is dealt with.