使用指针显式调用指向的对象的析构函数后,指针将持有哪种值?

问题描述

来自https://timsong-cpp.github.io/cppwp/basic.compound#3

指针类型的每个值都是以下之一:

  • 指向对象或函数的指针(据说该指针指向该对象或函数),或者
  • 超出对象末尾的指针([expr.add]),或
  • 该类型的空指针值,或
  • 无效的指针值。

使用指针显式调用对象的析构函数后,指针具有这四种值中的哪一种?例子:

#include <vector>

struct foo {
    std::vector<int> m;
};

int main()
{
    auto f = new foo;
    f->~foo();
    // What is the value of `f` here?
}

我不认为它可以是指向对象或函数的指针。不再有指向的对象 它不是函数指针。

我不认为它可以是对象末尾的指针。没有任何形式的指针运算,也没有涉及数组。

我不认为它可以是空指针值,因为指针不是nullptr。它仍然指向对象拥有的存储,您可以使用它执行放置new

我不认为它可以是无效的指针值。无效的指针值与存储持续时间的结束而非对象生存期相关联。 "A pointer value becomes invalid when the storage it denotes reaches the end of its storage duration"。存储仍然有效。

在我看来,指针没有指针值。我哪里出错了?

解决方法

它是指向对象的指针,但是对象不在其生命周期之内。

[basic.compound],footnote 42)中:

对于不在其生存期内的对象,这是它将占据或曾经占据的内存中的第一个字节。

,

它是一个指向不再存在的对象的指针。在标准列出的可能值中,仅指向对象的指针可以应用,但是仅当我们认为该对象的寿命之外的对象包含在该定义中时才适用。如果 Invalid 可能包含没有对象的存储指针,则可能适用。

如果这些都不适用,那么所有值的列表都将是有缺陷的。


如果要在存储中创建一个新对象,则将适用于此:

[basic.life]

如果在一个对象的生命周期结束之后并且在重新使用或释放​​该对象所占用的存储之前,在原始对象所占用的存储位置上创建了一个新对象,该对象指向原始对象,引用原始对象的引用或原始对象的名称将自动引用新对象,并且在新对象的生命周期开始后,如果原始对象是透明的,则可用于操作新对象。可被新对象替换(见下文)。