38

As mentioned in the title, I would like to know about the type of 'this' pointer.

I'm working on a project and I observed that the type of 'this' pointer is "ClassName * const this" on windows using VC++ 2008. Well I would want to know what is the need/requirement to make the this pointer a constant pointer. Thanks.

Purnima
  • 992
  • 1
  • 8
  • 15

4 Answers4

56

The type of this pointer is either ClassName * or const ClassName *, depending on whether it is inspected inside a non-const or const method of the class ClassName. Pointer this is not an lvalue.

class ClassName {
  void foo() {
    // here `this` has `ClassName *` type
  }

  void bar() const {
    // here `this` has `const ClassName *` type
  }
};

The observation you mentioned above is misleading. Pointer this is not an lvalue, which means that it cannot possibly have ClassName * const type, i.e. it cannot possible have a const to the right of the *. Non-lvalues of pointer type cannot be const or non-const. There's simply no such concept in C++ language. What you observed must be an internal quirk of the specific compiler. Formally, it is incorrect.

Here are the relevant quotes from the language specification (emphasis mine)

9.3.2 The this pointer

In the body of a non-static (9.3) member function, the keyword this is a prvalue expression whose value is the address of the object for which the function is called. The type of this in a member function of a class X is X*. If the member function is declared const, the type of this is const X*, if the member function is declared volatile, the type of this is volatile X*, and if the member function is declared const volatile, the type of this is const volatile X*. [ Note: thus in a const member function, the object for which the function is called is accessed through a const access path. —end note ]


It is worth nothing that back in the C++98/C++03 times several compilers used an internal implementational trick: they interpreted their this pointers as constant pointers, e.g. ClassName *const in a non-constant method of class ClassName. This apparently helped them to ensure non-modifiablity of this. GCC and MSVC are known to have used the technique. It was a harmless trick, since at language level this was not an lvalue and its constness was undetectable. That extra const would generally reveal itself only in diagnostic messages issued by the compiler.

However, with the advent of rvalue references in C++11 it became possible to detect this extra const on the type of this. For example, the following code is valid in C++11

struct S
{
  void foo() { S *&&r = this; }
};

Yet it will typically fail to compile in implementations that still use the aforementioned trick. GCC has since abandoned the technique. MSVC++ still uses it (as of VS2017), which prevents the above perfectly valid code from compiling in MSVC++.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
  • Exactly what I was expecting. But I do not see that way. the behaviour I'm observing is inside a non-const method of the so called `ClassName` class. Well I get to know the type using the VC++ intellisense which displays the type when you scroll over the variables. Could this be the possible reason why I'm getting incorrect type information. – Purnima May 20 '11 at 04:00
  • @Purnima: The type information you see is probably restricted to error messages only (and to Intellisense and stuff like that). I'm sure the core language sees the correct type of `this`. I.e. if you inspect the type of `this` using `typeid`, it will not have `const` to the right of the `*`. – AnT stands with Russia May 20 '11 at 04:05
  • @Andrey: Thank u for the prompt response. I indeed checked using `typeid` and got the correct type as expected. – Purnima May 20 '11 at 04:35
  • I couldn't agree more, hmm, if there is no C++0x standard. After that, `this` may have a type of rvalue pointer, if the object is a tmp obj like `ClassName().call()`. – neuront May 20 '11 at 06:59
  • @neuront: that doesn't make sense. The type of `this` (or any other expression) in a given scope is not determined by the call stack. – MSalters May 20 '11 at 09:00
  • @neuront: If you have a pointer to something, that something is guaranteed to be an lvalue. What I say above applies to `this` itself, not to what it points to. – AnT stands with Russia May 20 '11 at 14:07
  • @MSalters @Andrey Sorry, but I have made a mistake. Rvalue will only make sense on references, not pointers. – neuront May 21 '11 at 08:08
  • I just bumped across this piece of text from C++ Primer 4th ed: "In an ordinary `nonconst` member function, the type of `this` is a `const pointer` to the class type. We may change the value to which `this` points but cannot change the address that `this` holds. In a `const` member function, the type of `this` is a `const pointer to a const class-type` object. We may change neither the object to which this points nor the address that this holds." This means VC++ intellisense is correct. I wonder why does `typeid` return the type of `this` inside a non const method incorrectly? – Purnima May 27 '11 at 04:15
  • 4
    @Purnima: No. That means that your "C++ Primer 4th ed" is incorrect. I don't know whether this is a deliberate error (for simplification) or genuine error in the book, but saying that `this` is a "const pointer" is always incorrect. Again, `this` is an rvalue of scalar type. Rvalues of scalar type cannot be const or non-const. The fourth edition was published in 2001, which means it is rather old. It probably makes sense to check the later editions. The error might be fixed there. – AnT stands with Russia May 29 '11 at 03:05
  • @Andrey: I have also referred to The C++ Programming by Bjarne Stroustroup and it mentions the same way. – Purnima May 29 '11 at 03:15
  • @Purnima: The TC++PL book by Bjarne Stroustroup is well-known to contain more than a few errors, presumably deliberately introduced to make things simpler. For example, TC++PL claims that scalar types have constructors, which is absolutely incorrect. Anyway, books are not considered normative references. Only the language standard is. BTW, which chapter of TC++PL did you see this in? – AnT stands with Russia May 29 '11 at 05:20
  • @Purnima: I just found it in chapter 10 of TC++PL book. Yes, it states that. And yes, that's just another error in Stroustrup's book. – AnT stands with Russia May 29 '11 at 05:33
3

The const means you cannot change what the pointer points to.

ClassName *const

is much different from

const ClassName *

The latter is a pointer to an object and the object cannot be modified (using the pointer, anyway). The former is a pointer which cannot be re-pointed to another object (nor NULL), at least without resorting to nasty casting.

There is of course also the combination:

const ClassName *const

This would be a pointer which cannot be changed to point to something else, nor can it be used to change the object it points to.

As for why your compiler shows this pointers as being const, it does make sense that you are discouraged from making this point to an object other than the one it began with.

John Zwinck
  • 239,568
  • 38
  • 324
  • 436
  • +1 good analysis. In brief, it's the compiler tracking that you can't `this = ...` or `This& p = *this` (given `p` isn't `const`). – Tony Delroy May 20 '11 at 04:11
  • 14
    Literal `5` also cannot be changed or assigned to. You can't do `5 = 3`. However, the type of `5` is `int`. It is `int` and not `const int`. To say that `5` has type `const int` is incorrect. The same applies to `this` pointer. It is not an lvalue (just like `5` is not an lvalue). Something that is not an lvalue cannot be const or non-const. For this reason, `this` pointer cannot be `const` and the above analysis is totally incorrect from the formal point of view. – AnT stands with Russia May 20 '11 at 04:24
  • I prefer `ClassName const *` to `const ClassName *`. Same with `ClassName const * const` to `const ClassName * const`. Read from right to left, and it's easy to see where const is applied. – Thomas Eding May 20 '11 at 04:27
2

There were a lot of discussions above and main post didn't present correct answer. People might not dig comments so its better to share as main port (PS).

I did some investigation on Ubuntu as well as on VC++ but there is no correct output (using typeid(X).name ).


The type of this pointer for a member function of a class type X, is X* const. If the member function is declared with the const qualifier, the type of the this pointer for that member function for class X, is const X* const. MSDN link


Conceptually this is correct also, for normal member function is "X* const" that's why it isn't l-value (as you can't change its contents).

tashuhka
  • 5,028
  • 4
  • 45
  • 64
nky
  • 29
  • 3
-4

An excerpt from C++ Primer 4th ed: "In an ordinary nonconst member function, the type of this is a const pointer to the class type. We may change the value to which this points but cannot change the address that this holds. In a const member function, the type of this is a const pointer to a const class - type object. We may change neither the object to which this points nor the address that this holds." This means whatever VC++ intellisense was displaying is correct.

Purnima
  • 992
  • 1
  • 8
  • 15
  • 4
    Incorrect. The book, as well as VC++ Intellisense is wrong. Once again, `this` pointer is an rvalue (see 9.3.2/1 in language standard). Non-class rvalues cannot have const-qualified types (see 3.10/9 in language standard). Whatever any book claims is irrelevant, regardless of who wrote it. If some books contradicts the language specification, the book is in error. – AnT stands with Russia May 29 '11 at 05:24
  • 3
    It is quite possible that in early versions of the language specification `this` had a constant pointer type. However, when the C++98 standard was finalized, this was no longer the case. Your books are either outdated or simply erroneous. – AnT stands with Russia May 29 '11 at 05:38