c++ - 指向派生对象数组的基指针

标签 c++ standards

关注 question今天早些时候在这里问了很多类似主题的问题,我来这里是想从标准的角度来问这个问题。

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*(new-expression 的结果)可以是隐式转换为 Base*(C++11 草案,§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++ - 指向派生对象数组的基指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39623390/

相关文章:

c++ - 每次在 IRC 中显示新文本时显示新行

c++ - 使用 BOOST ASIO async_read_until 读取 mpstat 输出时文件意外结束

javascript - 关于 HTMLCollections 和命名属性的问题,继续使用?

c++ - 重载决策中的 const 指针

php - Magento:产品库中显示的相关产品图片

javascript - 像 $(.someClass) 这样的 JQuery 类选择器是否区分大小写?

c++ - WinSock2 C++ - 多个套接字存储为一个

c++ - 构造函数初始化列表顺序/分配问题

c++ - 将指向成员函数的指针作为模板参数传递。为什么这行得通?

c++ - 无限递归 C++