15

This earlier question asks what this[0] means in C#. In C++, this[0] means "the zeroth element of the array pointed at by this."

Is it guaranteed to not cause undefined behavior in C++ to refer to the receiver object this way? I'm not advocating for using this syntax, and am mostly curious whether the spec guarantees this will always work.

Thanks!

Community
  • 1
  • 1
templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
  • 1
    I'm pretty sure it's well-defined, going along the lines of how `&obj + 1` is. – chris May 20 '13 at 17:54
  • 3
    I've used it sometimes with gdb: say you did `p complex-expression-that-yields-pointer`, but you wanted to see the contents of the object, not the pointer, so press up, type `[0]` and done. No need to scroll to the beginning of the expression and add parenthesis (probably). – rodrigo May 20 '13 at 17:59

6 Answers6

19

For any valid object pointer p, p[0] is equivalent to *p. So this[0] is equivalent to *this. There's nothing more to it. Just like you can dereference any valid pointer using [0], you can dereference this with it.

In other words, it is just a "tricky" way to write *this. It can be used to obfuscate code. It can probably be used in some specific circumstances for useful purposes as well, since any standalone object can be thought of as an array of size 1. (From C++03, Additive operators: "For the purposes of these operators, a pointer to a nonarray object behaves the same as a pointer to the first element of an array of length one with the type of the object as its element type.")

P.S. As Johannes noted in the comments, by using C++11 features it is possible to come up with a context in which this is a pointer to an incomplete type. In that case this[0] expression becomes invalid, while *this expression remains valid.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
  • 5
    I am pretty sure you are aware of it, but the answer states it different. The following is illformed, and replacing `this[0]` by `*this` makes it wellformed. `struct A { auto f () -> decltype (this [0]); };`. – Johannes Schaub - litb May 20 '13 at 19:15
  • 2
    Right, what Johannes said, `p[0]` doesn't work when `p` is a pointer to an incomplete type. To add to that, the type could be incomplete because it isn't yet completed, as in Johannes's example, but it could also be because the type cannot be completed (such as `T(*)[]`). It (of course) also doesn't work for non-object pointer types. –  May 21 '13 at 18:09
11

this[0] is the same as *(this + 0), so indeed this is fine (albeit a bit weird).

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • 2
    Sorry for being pedantic, but does the ISO spec guarantee this? I'm well aware of this identity, but the spec often makes a distinction between objects and arrays. – templatetypedef May 20 '13 at 17:58
  • @templatetypedef, `&obj + 1` is valid despite whether `obj` is an array or a single object. I would assume the same applies here. – chris May 20 '13 at 18:01
  • 3
    @templatetypedef: Actually, the `[]` does not operate on arrays, only on pointers. The array decays into a pointer and the `[]` works with the pointer and the index. So, yes, it is guaranteed. – rodrigo May 20 '13 at 18:02
  • 5
    @templatetypedef: From C++03, Additive operators: "For the purposes of these operators, a pointer to a nonarray object behaves the same as a pointer to the first element of an array of length one with the type of the object as its element type." – AnT stands with Russia May 20 '13 at 18:05
3

Yep, it's the same thing as *this

weskpga
  • 2,017
  • 7
  • 29
  • 43
1

AFAIK basically this[0] is exactly the same as *this, as this is just a normal pointer. So yes it is safe to use.

array[1] would be the same as *(array + 1) (when array is valid) fyi...

Uroc327
  • 1,379
  • 2
  • 10
  • 28
0

It is equivalent (by definition) to *(this + 0), which is the same as *this. It is safe and well-defined, but weird.

Dietrich Epp
  • 205,541
  • 37
  • 345
  • 415
-2

this[0] is same as *(this + sizeof(this)*0) so it's quite safe

Added small test as answer to comment

struct A
{
    void * _a;
    int _b;

    A * getThis(int index)
    {
        return &(this[index]);
    }
};

int main(int argc, char * argv[])
{
    A mas[100];

    std::cout << ((long long) mas[0].getThis(50) == (long long) &(mas[50])) << std::endl;
    return 0;
}
Nikolay Viskov
  • 1,016
  • 6
  • 9
  • 7
    While your answer is *technically* correct. The `sizeof(this)` is superfluous and implies that `this[1]` is the same as `*(this + sizeof(this)*1)`. Or that `this[N]` is generally equivalent to `*(this + sizeof(this)*N)`. This is, of course, false. – Benjamin Lindley May 20 '13 at 17:58
  • @BenjaminLindley see small test that, I think, prove my point – Nikolay Viskov May 20 '13 at 18:10
  • 3
    I don't know what point you are trying to prove with your test. Did you understand my comment? My point is that `this[N]` is *not* equivalent to `*(this + sizeof(this)*N)`, but your original answer, in my opinion, implies that they are equivalent. The `sizeof(this)` is completely pointless, and only happens to work out because it is being multiplied by 0. But for any other value of `N` besides 0, it does not work. So why is it in your formula? – Benjamin Lindley May 20 '13 at 18:31
  • 2
    pointer+integer addition is already scaled by the size of the pointed-to object. `this[0]` happens to be the same as `*(this + sizeof(this)*0)`, but `this[N]` is *not* the same as `*(this + sizeof(this) * N)`'; rather, it's equivalent to `*(this + N)` (which is the object `N * sizeof *this` bytes, or more simply `N` *elements*, past the location pointed to by `this`). In any case, `sizeof(this)` is irrelevant; that gives you the size of the pointer, not the size of the pointed-to object. – Keith Thompson May 20 '13 at 18:37