c – 派生对象数组的基指针

在今天早些时候在这里提到的 question和许多类似的主题问题之后,我在这里从stadard的观点来询问这个问题.
struct Base
{
  int member;
};

struct Derived : Base
{
  int another_member;
};

int main()
{
  Base* p = new Derived[10]; // (1)
  p[1].member = 42; // (2)
  delete[] p; // (3)
}

根据标准(1)是格式正确的,因为Dervied *(这是新表达式的结果)可以隐式转换为Base *(C11草案,§4.10/ 3):

A prvalue of type “pointer to cv D”,where D is a class type,can be
converted to a prvalue of type “pointer to cv B”,where B is a base
class (Clause 10) of D. If B is an inaccessible (Clause 11) or
ambiguous (10.2) base class of D,a program that necessitates this
conversion is ill-formed. The result of the conversion is a pointer to
the base class subobject of the derived class object. The null pointer
value is converted to the null pointer value of the destination type.

(3)由于§5.3.5/ 3导致未定义的行为:

In the first alternative (delete object),if the static type of the
object to be deleted is different from its dynamic type,the static
type shall be a base class of the dynamic type of the object to be
deleted and the static type shall have a virtual destructor or the
behavior is undefined. In the second alternative (delete array) if the
dynamic type of the object to be deleted differs from its static type,
the behavior is undefined.

(2)是否符合标准,否则会导致程序不合格或未定义的行为?

编辑:更好的措辞

解决方法

如果你看表​​达式p [1],p是一个Base *(Base是一个完全定义的类型),1是一个int,所以根据ISO / IEC 14882:2003 5.2.1 [expr.sub]这个表达式是有效的,与*((p)(1))相同.

从5.7 [expr.add] / 5,当一个整数被添加一个指针时,结果只有在指针指向数组对象的元素并且指针算术的结果也指向该元素数组对象或数组的末尾. p然而,并不指向数组对象的元素,它指向Derived对象的基类子对象. Derived对象是数组成员,而不是Base子对象.

请注意,在5.7 / 4以下,对于加法运算符,Base子对象可以被视为大小为1的数组,因此在技术上您可以形成地址p 1,但是作为“一个最后一个元素”指针,它不指向一个Base对象,并尝试读取或写入它将导致未定义的行为.

相关文章

本程序的编译和运行环境如下(如果有运行方面的问题欢迎在评...
水了一学期的院选修,万万没想到期末考试还有比较硬核的编程...
补充一下,先前文章末尾给出的下载链接的完整代码含有部分C&...
思路如标题所说采用模N取余法,难点是这个除法过程如何实现。...
本篇博客有更新!!!更新后效果图如下: 文章末尾的完整代码...
刚开始学习模块化程序设计时,估计大家都被形参和实参搞迷糊...