What kind of value does a pointer hold after using it to explicitly call the pointed object's destructor?
Asked Answered
P

2

6

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

Every value of pointer type is one of the following:

  • a pointer to an object or function (the pointer is said to point to the object or function), or
  • a pointer past the end of an object ([expr.add]), or
  • the null pointer value for that type, or
  • an invalid pointer value.

After using a pointer to explicit call an object's destructor, which of these four kinds of value does the pointer have? Example :

#include <vector>

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

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

I don't believe it can be a pointer to an object or function. There is no longer an object to point to and it is not a function pointer.

I don't believe it can be a pointer past the end of an object. There wasn't any sort of pointer arithmetic and no array is involved.

I don't believe it can be a null pointer value since the pointer is not nullptr. It still points to the storage the object had, you could use it to perform placement new.

I don't believe it can be an invalid pointer value. Invalid pointer values are associated with the end of storage duration, not object lifetime. "A pointer value becomes invalid when the storage it denotes reaches the end of its storage duration". The storage is still valid.

It seems to me like there is no pointer value the pointer could have. Where did I go wrong?

Picnic answered 7/9, 2020 at 0:50 Comment(8)
Only the first point makes sense IMHO. Still points to an object, although the object is in an invalid state.Rubenstein
@Rubenstein It is my understanding that an object ceases to exist after its constructor has completed. Edit : I agree that it is probably the most likely answer, but I am curious as to how it could be.Asbestosis
The value of f doesn't change during, or as a result of, the explicit call of the destructor. Because of the destructor call, f now points at an object that has ceased to exist. Any attempt to use that object (e.g. dereference that pointer) gives undefined behaviour.Peba
@Peba That keeps coming up, but I don't believe that objects exist after their destructor has finished. I was pretty sure of this, but maybe that is where I was wrong. I'll post another question I guess. Edit : posted.Asbestosis
For most purposes, it is an invalid pointer as it point to an object that is not in a valid state.Cylix
@FrançoisAndrieux - The object no longer exists after the destructor call, since the destructor call marks its end of life. The destructor call doesn't change the value of any pointers that (before destruction) held the address of the object.Peba
@Peba I agree that it does not impact its representation. It still stores the same address. The question is does that representation now represent an object pointer or an invalid pointer value? An analogy would be invalidated iterators. When an interator is invalidated its representation does not change but the meaning of that representation changes. It changes despite non of its bits changing.Asbestosis
@FrançoisAndrieux - That pointer is to an object that no longer exists because its lifetime has ended. It is not necessarily an invalid pointer value - it can be compared with nullptr and test non-equal. The standard specifies that using an object outside its lifetime gives undefined behaviour. The standard also says nothing about what the meaning of the value of the pointer is after the object's lifetime has ended - which means, if you attempt to test "validity" of that pointer (beyond comparing it with nullptr) you are in the realms of undefined behaviour.Peba
Z
7

It's the pointer to the object, but the object is just not within its lifetime.

In [basic.compound], footnote 42):

For an object that is not within its lifetime, this is the first byte in memory that it will occupy or used to occupy.

Zeldazelde answered 7/9, 2020 at 1:23 Comment(10)
See the comment to the other answer. I'm not sure that this counts as an object not within its lifetime. I believe that this only includes objects being constructed or destructed. But if I am wrong, then this is probably the right answer.Asbestosis
@FrançoisAndrieux I believe that this only includes objects being constructed or destructed. Objects during construction and destruction are specified to occupy storage. The footnote says "it will occupy or used to occupy". So...Melmela
@FrançoisAndrieux I agree that objects being constructed and destructed still occupy storage. So, the footnote is not about the period of construction or destruction, because it says "used to occupy".Melmela
If we assume this is the correct answer, it would imply that every storage simultaneously contains every object that could possibly be constructed within it How so?Melmela
@LanguageLawyer I had to read that a few times, but I see what you mean. It would be strange to use the term "used to" here if objects weren't considered to exist after their destruction.Asbestosis
@FrançoisAndrieux I don't think it is that important to figure out does an object "exist" or not, as long as there is agreement that one can point to an object outside its lifetime (and period of ...) and perform pointer arithmetic on such pointer etc.Melmela
@LanguageLawyer It is the same thing. Being able to point to something implies that it exists.Asbestosis
@FrançoisAndrieux I think it is the question of the definition of "exist". Or, maybe not. Maybe it should mean it exists.Melmela
the footnote basically says the the pointer to a byte of the storage is a pointer to an object that can potentially be constructed to occupy that storage starting at that byte No, it doesn't say this. It says that a pointer to some specific object (outside lifetime) represents the address of byte the object will occupy or used to occupy. You a have pointer to specific object, not "a byte of storage" and/or all objects which can be placed there.Melmela
I'm not sure if there is such a thing as "an object not within its lifetime" after its destructor has ended. I've asked another question about that here and if it checks out I'll accept this answer. Edit : though the quoted passage seems to imply the pointer no longer points to an object but instead to storage. Is storage an object? It would have to be for the pointer to be considered a pointer to object. If it isn't an object then the question remains.Asbestosis
E
1

It is a pointer that pointed to the object that no longer exists. Of the possible values that the standard lists, only pointer to an object can apply, but only if we consider objects outside of their lifetime to be included in that definition. Invalid could apply if that could include pointers to storage with no objects.

If neither of these can apply, then the list of all values would be defective.


If you were to create a new object into the storage, then this would apply:

[basic.life]

If, after the lifetime of an object has ended and before the storage which the object occupied is reused or released, a new object is created at the storage location which the original object occupied, a pointer that pointed to the original object, a reference that referred to the original object, or the name of the original object will automatically refer to the new object and, once the lifetime of the new object has started, can be used to manipulate the new object, if the original object is transparently replaceable (see below) by the new object.

Elbertelberta answered 7/9, 2020 at 1:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.