给定以下代码
operator new[]
以及各种错误的版本
delete
:
#include <iostream>
class Test {
public:
Test() { std::cout << "Test()\n"; }
~Test() { std::cout << "~Test()\n"; }
};
int main()
{
void* p = operator new[](10 * sizeof(Test));
Test* test = new (p) Test();
test->~Test();
// delete p; // UB1
// delete[] p; // UB2
// delete[] test; // UB3
// operator delete[](test); // UB4?
operator delete[](p);
std::cout << "End\n";
}
继续活着
https://godbolt.org/z/zG3nfzsv6
你能解释一下为什么UB2到UB4是未定义的行为吗?用一些外行术语解释一下C++20草案N4861的标准,第7.6.2.8节[删除],也许还有第7.6.2.7节[新增]?
这是我的尝试。我对UB1很有信心,但对UB2和UB3不太有信心,更不用说对UB4了。
UB1
(强调我)
§ 7.6.2.8 (1)
删除表达式:
::选择删除强制转换表达式
::opt-delete[]强制转换表达式
第一种选择是使用单个对象删除表达式
,第二个是数组删除表达式。
§ 7.6.2.8 (2)
在一个
单对象删除表达式
,delete操作数的值可以是空指针值
指向非数组对象的指针
例如由先前的新表达式创建的对象(11.7)或指向表示此类对象的基类的子对象(6.7.2)的指针。
如果没有,则行为未定义。
所以,为了
删除
没有
[]
我不能使用数组指针。但我做到了,所以我有UB。好的。
UB2至UB4
(强调我)
在数组中删除
表达
,delete操作数的值可能是空指针值或导致的指针值
从以前的数组中生成新表达式
.
74
如果没有,则行为未定义。
好吧,我有一个来自以前新表达式的数组。
[注意:这意味着delete表达式的语法必须与new分配的对象类型匹配,
不是新表达式的语法
.end注释]
附带问题:为什么这意味着什么?
好吧,我有
操作员新[]
这个注释告诉我,删除的语法可能不同。我不一定需要
operator delete[]
而是与对象类型相匹配的东西。
附带问题:什么
是
我的对象的类型?我的指针p是
void*
但是
void
不是对象类型。p是否指向a
void[]
和
无效[]
是对象类型吗?
§ 7.6.2.8 (11)
对于数组删除表达式
delete对象是数组对象。当执行删除表达式时,所选的释放函数
应在单个对象删除表达式中调用已删除对象的地址,或
在数组删除表达式中针对数组分配开销(7.6.2.7)适当调整已删除对象,
作为其第一个论点。
对不起,我对此一无所知。我只是有一种直觉,这可能是相关的。