C++标准中关于子对象的一些困惑

Some puzzles about the subobject in the C++ Standard

C++ 标准定义左值的“动态类型”概念如下:

dynamic type

<glvalue> type of the most derived object (1.8) to which the glvalue denoted by a glvalue expression refers [Example: if a pointer (8.3.1) p whose static type is “pointer to class B” is pointing to an object of class D, derived from B (Clause 10), the dynamic type of the expression *p is “D.” References (8.3.2) are treated similarly. —end example ]

如果泛左值所指的不是最派生对象,如何解释这个定义?它是否意味着“最派生对象的类型 包含对象 由泛左值表达式表示的泛左值所指的对象”?

另一个谜题是关于C++标准5.7的第4段:

... If the pointer operand points to an element of an array object, ...

我想问一下,如果指针操作数指向数组对象的一个​​元素的子对象,这个条件是否成立。举个例子,如果不成立,那么下面代码中的行为是未定义的,对吧?

D d[10];
B *p = d; //B is a base class of D
p += 2;   //undefined behavior?

"Question" 在这里可能比 "puzzle" 更好。

总之,关于您展示的那段代码,这很有趣。它不是未定义的,因为那段代码中的所有内容都完全由标准定义。然而,如果您希望指针算法进行动态类型识别,那么结果不是您所期望的。

特别是,p 将指向距离数组开头 2 B 个大小,而不是 2 D 个大小。同样,这是完全明确定义的。然而,访问该内存可能没有明确定义。

How is this definition interpreted if what the glvalue refers to is not the most derived object?

如果 glvalue 引用一个有效对象,它总是 构造的最派生对象,不一定是基类型的最派生类型。

示例:

class Base {};
class Derived1 : public Base {};
class Derived2 : public Derived1 {};

Base* ptr = new Derived1;

*ptr 指的是 Derived1,而不是 Derived2,因为构造的对象是 Derived1.

类型
D d[10];
B *p = d; //B is a base class of D
p += 2;   //undefined behavior?

是的,这是未定义的行为。

措辞清晰。最派生的对象暗示是一个完整的对象、数据成员或数组元素,即它不是基础 class 子对象。

WG21/N4527

1.8 The C++ object model [intro.object]

2 Objects can contain other objects, called subobjects. A subobject can be a member subobject (9.2), a base class subobject (Clause 10), or an array element. An object that is not a subobject of any other object is called a complete object.

3 For every object x, there is some object called the complete object of x, determined as follows:

(3.1) — If x is a complete object, then x is the complete object of x.

(3.2) — Otherwise, the complete object of x is the complete object of the (unique) object that contains x.

4 If a complete object, a data member (9.2), or an array element is of class type, its type is considered the most derived class, to distinguish it from the class type of any base class subobject; an object of a most derived class type or of a non-class type is called a most derived object.

D d[10];
B *p = d; //B is a base class of D
p += 2;   //undefined behavior?

毫无疑问,这有未定义的行为。没有关于派生 classes 的附加规则。并且由于表达式 p += 2 的每个操作数都是纯右值,因此不涉及动态类型的泛左值。

编辑:请注意,纯右值的动态类型与其静态类型相同。