Is the value of `this` pointer constant during the object's lifetime?
Asked Answered
A

3

19

Is the value of this pointer guaranteed to be constant during a lifetime of a particular object? I can't imagine a case where it would change, but don't know whether I am not missing something.

Artificial answered 15/1, 2020 at 10:17 Comment(2)
The value of this pointer always is the value of the address of the object on which the function was called on. So the question is equivalent with 'can an object change its memory address over life time?'Milagro
Worth noting: if one talks about lifespan informally, an object which is moved via std::move would change this pointers. Formally we would say those are two different objects, but informally one may think of them as "the same," which could breed confusion if one is not paying attention.Beach
B
28

Is the value of this pointer guaranteed to be constant during a lifetime of a particular object?

Yes.

As user Aconcagua puts it: the value of this pointer always is the value of the address of the object on which the function was called on1. So the question is equivalent with:

Can an object change its memory address over life time?

This is not possible, by definition of lifetime2. The lifetime of an object begins when or after its storage is obtained and ends before of when it is released.


1) [class.this]/1

In the body of a non-static ([class.mfct]) member function, the keyword this is a prvalue whose value is a pointer to the object for which the function is called.

2) [basic.life]/1 (emphasis mine)

The lifetime of an object or reference is a runtime property of the object or reference. A variable is said to have vacuous initialization if it is default-initialized and, if it is of class type or a (possibly multi-dimensional) array thereof, that class type has a trivial default constructor. The lifetime of an object of type T begins when:

  • storage with the proper alignment and size for type T is obtained, and
  • its initialization (if any) is complete (including vacuous initialization) ([dcl.init]), except that if the object is a union member or subobject thereof, its lifetime only begins if that union member is the initialized member in the union ([dcl.init.aggr], [class.base.init]), or as described in [class.union].

The lifetime of an object o of type T ends when:

  • if T is a non-class type, the object is destroyed, or
  • if T is a class type, the destructor call starts, or
  • the storage which the object occupies is released, or is reused by an object that is not nested within o ([intro.object]).
Bodyguard answered 15/1, 2020 at 10:21 Comment(12)
Does this mean that it would be impossible (illegal) for a sufficiently complex runtime to implement automated memory compaction for a C++ program? Or does it just mean that it would need to behave "as-if", so as to provide the same value of this every time, regardless of movements in the heap?Dinosaurian
Hmmm, I'm not even sure how that could be made to work. Each object would need to keep an "identity" that's used as this, and dereferencing operations would need to use the "identity" through a lookup table maintaining by the runtime to access the real objectsDinosaurian
@Alexander-ReinstateMonica is a pointer guaranteed to be the address of an object, or is the compiler free to add a level of indirection? The lookup table idea seems workable.Jolty
@MarkRansom I don't know, but it would at least need to be de-reference-able. The lookup table is a total non-starter tho, it'll absolutely wreck performance.Dinosaurian
@Alexander-ReinstateMonica the vtable is a similar concept that reduces performance, but it's accepted since the benefits outweigh the downside. Modern processors are really efficient with indirection.Jolty
@MarkRansom Heap compaction already has significant performance and complexity downsides, requiring it to indirect everything only makes it way worse. If the whole point of it is performance improvement, and it doesn't improve performance, there's not much a point, eh? :P And besides, vtables are relatively rare in C++, where calls are non-virtual by default, and virtual functions are de-virtualizeed by the optimizer where possibleDinosaurian
@Alexander-ReinstateMonica Changing ptr isn't doable. Not even on elaborate systems. Not in a low level langage (C/C++). Except maybe in very special cases.V2
@MarkRansom A vtable is a struct not an array. It doesn't have ptr arithmetic, etc. It doesn't have sub-members (members of members). Ptrs in C/C++ can point in the middle of objects which makes all GC (inexact and non compacting) more complicated. (There are ptr-to-members but they support only access not arithmetic.) Vtables aren't needed to access members except in morally virtual bases.V2
@MarkRansom "is a pointer guaranteed to be the address of an object, or is the compiler free to add a level of indirection?" By definition that ptr is the address of an object, but "address" could be an high level abstract concept. But then if you introduce indirection, you need atomicity, you need locking, you need a bunch of additional work on all accesses of any object, if there are threads. Simply by the look and feel of it I can it's unworkable (and I haven't even considered the fact C/C++ doubles as a low level language).V2
To even have a lookup table, you would need to turn ptrs into base_addr+offset, and then turn base_addr into a ref into a table index. Then ptr arithmetic could work on offset and not base_addr. So at least that is workable but would make ptr access much more complex, even before we started making sure GC is safe. It's totally unlike Java or SML where you get these properties for free (but then you have a lot more dyn alloc w/ these runtime models for the same number of high level "objects").V2
@V2 you make good points, and I'm no longer arguing that indirection would be practical. It still makes a good thought experiment though.Jolty
Even we can restructure our house, we are not allowed to change the address.Vaccaro
A
8

An object has a region of storage. this points there.

[intro.object]/1

An object occupies a region of storage in its period of construction ([class.cdtor]), throughout its lifetime, and in its period of destruction ([class.cdtor]).

Arbour answered 15/1, 2020 at 10:23 Comment(0)
T
-1

The value of this is guaranteed to be constant if the program ever reads it, if subsequently some bits of the read value are impossible to garbage collect or if subsequently some bits of the read value escaped outside of the program. In all other cases, it behaves like a Schrödinger's cat, that is, it is constant and variable at the same time.

Tightlipped answered 23/1, 2020 at 7:37 Comment(4)
Sorry, don't understand at all. What is to garbage collect and to escape outside of the program?Artificial
@DanielLangr The bits of the value of the identifier thisTightlipped
This does not answer my question. What is to garbage collect some bits? Or to escape them outside of the program?Artificial
@DanielLangr It is hard to explain in a small piece of textTightlipped

© 2022 - 2024 — McMap. All rights reserved.