【发布时间】:2021-08-11 05:33:54
【问题描述】:
我想知道以下是否未定义?
int main()
{
struct Doggy { int a; ~Doggy() {} };
Doggy* p = new Doggy[100];
p[50].~Doggy();
p[50].a = 3; // Is this not allowed? The destructor was called on an
// object occupying that area of memory.
// Can I access it safely?
if (p[50].a == 3);
}
我想这通常很好知道,但我特别想知道的原因是我有一个由数组组成的数据结构,其中桶可以通过设置一个值来为空,有点像桶一个哈希表数组。当桶被清空时,会调用析构函数,但是在调用析构函数后检查并设置空状态我想知道它是否非法。
稍微详细一点,假设我有一个对象数组,每个对象可以在每个桶中表示为空,例如:
struct Handle
{
int value = 0; // Zero is null value
~Handle(){}
};
int main()
{
Handle* p = new Handle[100];
// Remove object 50
p[50].~Handle();
p[50].value = 0; // Set to null
if (p[50].value == 0) ; // Then it's null, can I count on this?
// Is this defined? I'm accessing memory that was occupied by
// object that was destroyed.
}
【问题讨论】:
-
您是否使用placement new 来创建存储桶?
-
是的,如果在适当位置创建了一个新对象。但我想知道,因为对象本身可能是可空的,并且可以使用对象本身中设置为空值的成员来检查映射中的存储桶(值)中是否存在对象。但我想知道是否可以在调用析构函数后检查它是否为 null,就像我上面的例子一样。
-
看来
std::optional在这里可能有用。 -
是的,我可能会使用类似的东西,但我有兴趣从技术角度了解这个问题的答案。 optional 之类的东西会保留一个布尔值,对于一个 8 字节的结构来说,每个对象可能会浪费 7 个字节。这通常没什么大不了的,但是如果可以将空值存储在结构本身中,我有兴趣知道这个问题的答案。
-
stackoverflow.com/questions/6500313/… -- 顺便说一句。特别是使用向量 new 是一种代码味道。
标签: c++ language-lawyer undefined-behavior