在今天早些时候从这里提出的一个问题以及众多类似主题的问题后,我想从标准的角度来讨论这个问题。
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):
类型为“指向cv D”的prvalue可以转换为类型为“指向cv B”的prvalue, 其中B是D的基类(Clause 10)。 如果B是D的不可访问(Clause 11)或 有歧义的(10.2)基类,则需要此转换的程序是不良构的。 转换的结果是指向派生类对象的基类子对象的指针。 空指针值被转换为目标类型的空指针值。
(3)
由于§5.3.5 / 3存在未定义的行为,因此会导致未定义的行为:
在第一种情况下(删除对象),如果要删除的对象的静态类型与其动态类型不同, 则静态类型必须是要删除的对象的动态类型的基类,且静态类型必须具有虚拟析构函数,否则行为是未定义的。 在第二种情况下(删除数组),如果要删除的对象的动态类型与其静态类型不同,则行为是未定义的。
根据标准,(2)
是否合法?会导致良构程序还是未定义的行为?
(p + n)
使用p
的静态类型来计算偏移量,但我有一种感觉,关于operator+
的段落并没有暗示这一点。 - Vitus