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

前端之家收集整理的这篇文章主要介绍了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&C++相关文章