Type of 'this' pointer
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.
Solution 1:
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++.
Solution 2:
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.
Solution 3:
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).