Difference between revisions of "cpp/language/this"
m (→Syntax) |
m (Updated the version marks.) |
||
Line 9: | Line 9: | ||
The keyword {{tt|this}} is a {{rlp|value_category|prvalue}} {{rlp|expressions|expression}} whose value is the address of the {{rlp|overload resolution|implicit object parameter}} (object on which the non-static member function is being called). It can appear in the following contexts: | The keyword {{tt|this}} is a {{rlp|value_category|prvalue}} {{rlp|expressions|expression}} whose value is the address of the {{rlp|overload resolution|implicit object parameter}} (object on which the non-static member function is being called). It can appear in the following contexts: | ||
@1@ Within the body of any non-static {{rlp|member functions|member function}}, including {{rlp|initializer list|member initializer list}} | @1@ Within the body of any non-static {{rlp|member functions|member function}}, including {{rlp|initializer list|member initializer list}} | ||
− | @2@ within the {{rlp|function|declaration}} of a non-static member function anywhere after the (optional) cv-qualifier sequence, including {{rlp|except_spec|dynamic exception specification}} | + | @2@ within the {{rlp|function|declaration}} of a non-static member function anywhere after the (optional) cv-qualifier sequence, including |
− | @3@ within {{rlp|data_members#Member_initialization|default member initializer}} | + | {{rrev|until=c++17|* {{rlp|except_spec|dynamic exception specification}},}} |
+ | {{rrev|since=c++11| | ||
+ | * {{rlp|noexcept_spec|noexcept specification}}, and | ||
+ | * the trailing return type | ||
+ | }} | ||
+ | |||
+ | {{rrev|since=c++11| | ||
+ | @3@ within {{rlp|data_members#Member_initialization|default member initializer}} | ||
+ | }} | ||
The type of {{tt|this}} in a member function of class {{tt|X}} is {{tt|X*}} (pointer to X). If the member function is {{rlp|member_functions|cv-qualified}}, the type of {{tt|this}} is {{tt|cv X*}} (pointer to identically cv-qualified X). Since constructors and destructors cannot be cv-qualified, the type of {{tt|this}} in them is always {{tt|X*}}, even when constructing or destroying a const object. | The type of {{tt|this}} in a member function of class {{tt|X}} is {{tt|X*}} (pointer to X). If the member function is {{rlp|member_functions|cv-qualified}}, the type of {{tt|this}} is {{tt|cv X*}} (pointer to identically cv-qualified X). Since constructors and destructors cannot be cv-qualified, the type of {{tt|this}} in them is always {{tt|X*}}, even when constructing or destroying a const object. | ||
Line 19: | Line 27: | ||
{{source|1= | {{source|1= | ||
template<typename T> | template<typename T> | ||
− | struct B { | + | struct B |
+ | { | ||
int var; | int var; | ||
}; | }; | ||
template<typename T> | template<typename T> | ||
− | struct D : B<T> { | + | struct D : B<T> |
− | D() { | + | { |
+ | D() | ||
+ | { | ||
// var = 1; // error: 'var' was not declared in this scope | // var = 1; // error: 'var' was not declared in this scope | ||
this->var = 1; // ok | this->var = 1; // ok | ||
Line 35: | Line 46: | ||
{{source|1= | {{source|1= | ||
extern struct D d; | extern struct D d; | ||
− | struct D { | + | struct D |
+ | { | ||
D(int a) : a(a), b(d.a) {} // b(a) or b(this->a) would be correct | D(int a) : a(a), b(d.a) {} // b(a) or b(this->a) would be correct | ||
int a, b; | int a, b; | ||
Line 42: | Line 54: | ||
}} | }} | ||
− | It is possible to execute {{c|delete this;}}, if the program can guarantee that the object was allocated by {{c|new}}, however, this renders every pointer to the deallocated object invalid, including the {{tt|this}} pointer itself: after {{c|delete this;}} returns, such member function cannot refer to a member of a class (since this involves an implicit dereference of {{tt|this}}) and no other member function may be called. This is used, for example, in the member function of the control block of {{lc|std::shared_ptr}} responsible for decrementing the reference count, when the last reference to the managed object goes out of scope. | + | It is possible to execute {{c|delete this;}}, if the program can guarantee that the object was allocated by {{c|new}}, however, this renders every pointer to the deallocated object invalid, including the {{tt|this}} pointer itself: after {{c|delete this;}} returns, such member function cannot refer to a member of a class (since this involves an implicit dereference of {{tt|this}}) and no other member function may be called. |
+ | {{rrev|since=c++11| | ||
+ | This is used, for example, in the member function of the control block of {{lc|std::shared_ptr}} responsible for decrementing the reference count, when the last reference to the managed object goes out of scope. | ||
+ | }} | ||
{{source|1= | {{source|1= | ||
<!-- libreoffice i18nlangtag/source/languagetag/simple-langtag.cxx --> | <!-- libreoffice i18nlangtag/source/languagetag/simple-langtag.cxx --> | ||
Line 90: | Line 105: | ||
}; | }; | ||
− | class Outer { | + | class Outer |
+ | { | ||
int a[sizeof(*this)]; // error: not inside a member function | int a[sizeof(*this)]; // error: not inside a member function | ||
unsigned int sz = sizeof(*this); // OK: in default member initializer | unsigned int sz = sizeof(*this); // OK: in default member initializer | ||
− | void f() { | + | void f() |
+ | { | ||
int b[sizeof(*this)]; // OK | int b[sizeof(*this)]; // OK | ||
− | struct Inner { | + | struct Inner |
+ | { | ||
int c[sizeof(*this)]; // error: not inside a member function of Inner | int c[sizeof(*this)]; // error: not inside a member function of Inner | ||
}; | }; |
Revision as of 01:07, 15 September 2021
Syntax
this
|
|||||||||
The keyword this
is a prvalue expression whose value is the address of the implicit object parameter (object on which the non-static member function is being called). It can appear in the following contexts:
(until C++17) |
|
(since C++11) |
3) within default member initializer
|
(since C++11) |
The type of this
in a member function of class X
is X*
(pointer to X). If the member function is cv-qualified, the type of this
is cv X*
(pointer to identically cv-qualified X). Since constructors and destructors cannot be cv-qualified, the type of this
in them is always X*
, even when constructing or destroying a const object.
When a non-static class member is used in any of the contexts where the this
keyword is allowed (non-static member function bodies, member initializer lists, default member initializers), the implicit this->
is automatically added before the name, resulting in a member access expression (which, if the member is a virtual member function, results in a virtual function call).
In class templates, this
is a dependent expression, and explicit this->
may be used to force another expression to become dependent.
template<typename T> struct B { int var; }; template<typename T> struct D : B<T> { D() { // var = 1; // error: 'var' was not declared in this scope this->var = 1; // ok } };
During construction of an object, if the value of the object or any of its subobjects is accessed through a glvalue that is not obtained, directly or indirectly, from the constructor's this
pointer, the value of the object or subobject thus obtained is unspecified. In other words, the this pointer cannot be aliased in a constructor:
extern struct D d; struct D { D(int a) : a(a), b(d.a) {} // b(a) or b(this->a) would be correct int a, b; }; D d = D(1); // because b(d.a) did not obtain a through this, d.b is now unspecified
It is possible to execute delete this;, if the program can guarantee that the object was allocated by new, however, this renders every pointer to the deallocated object invalid, including the this
pointer itself: after delete this; returns, such member function cannot refer to a member of a class (since this involves an implicit dereference of this
) and no other member function may be called.
This is used, for example, in the member function of the control block of std::shared_ptr responsible for decrementing the reference count, when the last reference to the managed object goes out of scope. |
(since C++11) |
class ref { // ... void incRef() { ++mnRef; } void decRef() { if (--mnRef == 0) delete this; } };
Example
class T { int x; void foo() { x = 6; // same as this->x = 6; this->x = 5; // explicit use of this-> } void foo() const { // x = 7; // Error: *this is constant } void foo(int x) // parameter x shadows the member with the same name { this->x = x; // unqualified x refers to the parameter // 'this->' required for disambiguation } int y; T(int x) : x(x), // uses parameter x to initialize member x y(this->x) // uses member x to initialize member y {} T& operator= ( const T& b ) { x = b.x; return *this; // many overloaded operators return *this } }; class Outer { int a[sizeof(*this)]; // error: not inside a member function unsigned int sz = sizeof(*this); // OK: in default member initializer void f() { int b[sizeof(*this)]; // OK struct Inner { int c[sizeof(*this)]; // error: not inside a member function of Inner }; } }