6

我可以像下面的代码一样使用 smth:

int main()
{
    int* foo = new int;
    double* bar = reinterpret_cast<double*>(foo);
    delete bar;
}

是UB吗?

我认为我们只需要为 operator new 返回的指针调用 operator delete,但是在这种情况下如何进行强制转换呢?

我认为它是 UB,因为 reinterpret_cast 不对结果指针提供任何保证。我对吗?

有人可以从标准中发布正确的报价吗?

4

3 回答 3

6

§5.3.5/2 “在第一种选择(删除对象)中,delete 的操作数的值可以是空指针值、指向由先前的 new 表达式创建的非数组对象的指针或指向表示此类对象的基类(第 10 条)的子对象(1.8)。如果不是,则行为未定义。由于 bar指向 a double,因此它不指向由先前的 new 表达式(它创建了 a int)创建的对象。

于 2013-06-24T11:28:12.187 回答
2

从 5.3.5-3 开始:

在第一种选择(删除对象)中,如果待删除对象的静态类型与其动态类型不同,则静态类型应为待删除对象的动态类型的基类,静态类型应具有虚拟析构函数或行为未定义。

抛开reinterpret_cast这里使用可能出现的问题不谈,这是UB,因为类型不匹配。想象一些非平凡的类型,然后你可以很容易地看到这是因为“错误”的 dtor 会被调用。

此外,将结果reinterpret_cast用于除将其返回之外的任何其他内容大多未在标准中指定。

于 2013-06-24T11:29:11.540 回答
0

给你:

5.3.5点3:在第一种选择(删除对象)中,如果要删除的对象的静态类型与其动态类型不同,则静态类型应为要删除的对象的动态类型的基类并且静态类型应具有虚拟析构函数或行为未定义。

至于什么是静态类型和动态类型的问题:

1.3.7 动态类型 (glvalue)
由 glvalue 表达式表示的 glvalue 所指的最派生对象 (1.8) 的类型 [ 示例:如果静态类型为“指向 B 类的指针”的指针 (8.3.1) p 是指向从 B 派生的 D 类对象(第 10 条),表达式 *p 的动态类型是“D”。参考文献(8.3.2)的处理方式类似。—结束示例]

1.3.23 静态类型
不考虑执行语义对程序进行分析得出的表达式(3.9)的类型 [注:表达式的静态类型只取决于表达式出现的程序的形式,在程序正在执行。——尾注]

于 2013-06-24T11:28:38.330 回答