Namespaces
Variants
Views
Actions

Difference between revisions of "cpp/language/this"

From cppreference.com
< cpp‎ | language
(; omitted)
(Added CWG issue #2869 DR.)
 
(10 intermediate revisions by 4 users not shown)
Line 7: Line 7:
 
{{sdsc end}}
 
{{sdsc end}}
  
The keyword {{tt|this}} is a {{rev inl|until=c++11|{{rlp|value category#rvalue|rvalue}}}}{{rev inl|since=c++11|{{rlp|value category#prvalue|prvalue}}}} {{rlp|expressions|expression}} whose value is the address of the {{rlp|overload resolution#Implicit object parameter|implicit object parameter}} (object on which the non-static member function is being called). It can appear in the following contexts:
+
The expression {{c|this}} is a {{rlps|value category#prvalue}} {{rlp|expressions|expression}} whose value is the address of the {{rlpsd|overload resolution#Implicit object parameter}} (object on which the implicit object 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 {{rlp|member functions|implicit object member function}}, including {{rlp|initializer list|member initializer list}}{{rev inl|since=c++11|, and {{rlp|lambda#closure type fun operator|lambda expression body}}}}.
@2@ within the {{rlp|function|declaration}} of a non-static member function anywhere after the (optional) cv-qualifier sequence, including
+
@2@ Within the {{rlp|function|declaration}} of any implicit object member function anywhere after the (optional) cv-qualifier sequence, including the {{rlp|exceptions|exception specification}}{{rev inl|since=c++11| and the trailing return type}}.
{{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|
 
{{rrev|since=c++11|
@3@ within {{rlp|data members#Member initialization|default member initializer}}
+
@3@ Within {{rlp|data members#Member initialization|default member initializer}}.
 +
@4@ Within {{rlp|lambda#Lambda capture|capture list}} of a lambda expression.
 
}}
 
}}
  
{{tt|this}} can only associate with the innermost enclosing class of its appearance, even if the appearance is invalid in the context:
+
===Explanation===
 +
{{c|this}} can only associate with the innermost enclosing class of its appearance, even if the appearance is invalid in the context:
 
{{source|1=
 
{{source|1=
 
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
                                   // 'this' is not associated with Outer
+
                                   // “this” is not associated with Outer
 
                                   // even if it is inside a member function of Outer
 
                                   // even if it is inside a member function of Outer
 
         };
 
         };
Line 39: Line 38:
 
}}
 
}}
  
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#member functions with cv-qualifiers|declared with a cv-qualifier sequence}} ''cv'', the type of {{tt|this}} is {{tt|''cv'' X*}} (pointer to identically cv-qualified X). Since constructors and destructors cannot be declared with cv-qualifiers, the type of {{tt|this}} in them is always {{tt|X*}}, even when constructing or destroying a const object.
+
The type of {{c|this}} in a member function of class {{tt|X}} is {{tt|X*}} (pointer to X). If the member function is {{rlp|member functions#member functions with cv-qualifiers|declared with a cv-qualifier sequence}} ''cv'', the type of {{c|this}} is {{tt|''cv'' X*}} (pointer to identically cv-qualified X). Since constructors and destructors cannot be declared with cv-qualifiers, the type of {{c|this}} in them is always {{tt|X*}}, even when constructing or destroying a const object.
  
When a non-static class member is used in any of the contexts where the {{tt|this}} keyword is allowed (non-static member function bodies, member initializer lists, default member initializers), the implicit {{ttb|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, {{c|this}} is a {{rlp|dependent name|dependent expression}}, and explicit {{c|this->}} may be used to force another expression to become dependent.
 
+
In class templates, {{tt|this}} is a {{rlp|dependent name|dependent expression}}, and explicit {{tt|this->}} may be used to force another expression to become dependent.
+
 
{{source|1=
 
{{source|1=
 
template<typename T>
 
template<typename T>
Line 56: Line 53:
 
     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 62: Line 59:
 
}}
 
}}
  
{{rlp|constructor|During construction}} of an {{mark unreviewed dr|cwg}}<!-- was only const until cwg2271 --> 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 {{tt|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:
+
{{rlp|constructor|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 {{c|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:
 
{{source|1=
 
{{source|1=
 
extern struct D d;
 
extern struct D d;
 +
 
struct D
 
struct D
 
{
 
{
Line 70: Line 68:
 
     int a, b;
 
     int a, b;
 
};
 
};
 +
 
D d = D(1); // because b(d.a) did not obtain a through this, d.b is now unspecified
 
D d = D(1); // because b(d.a) did not obtain a through this, d.b is now unspecified
 
}}
 
}}
  
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.
+
It is possible to execute {{c|delete this;}}, if the program can guarantee that the object was allocated by {{c/core|new}}, however, this renders every pointer to the deallocated object invalid, including the {{c|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.
+
This can be used in the member function of the reference-counting pointer {{rev inl|since=c++11|(for example, {{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 86: Line 85:
 
};
 
};
 
}}
 
}}
 +
 +
===Keywords===
 +
{{ltt|cpp/keyword/this}}
  
 
===Example===
 
===Example===
Line 94: Line 96:
 
{
 
{
 
     int x;
 
     int x;
 
+
   
 
     void foo()
 
     void foo()
 
     {
 
     {
Line 100: Line 102:
 
         this->x = 5; // explicit use of this->
 
         this->x = 5; // explicit use of this->
 
     }
 
     }
 
+
   
 
     void foo() const
 
     void foo() const
 
     {
 
     {
//     x = 7; // Error: *this is constant
+
    // x = 7; // Error: *this is constant
 
     }
 
     }
 
+
   
 
     void foo(int x) // parameter x shadows the member with the same name
 
     void foo(int x) // parameter x shadows the member with the same name
 
     {
 
     {
 
         this->x = x; // unqualified x refers to the parameter
 
         this->x = x; // unqualified x refers to the parameter
                     // 'this->' required for disambiguation
+
                     // “this->” is required for disambiguation
 
     }
 
     }
 
+
   
 
     int y;
 
     int y;
 
     T(int x) : x(x),      // uses parameter x to initialize member x
 
     T(int x) : x(x),      // uses parameter x to initialize member x
 
               y(this->x) // uses member x to initialize member y
 
               y(this->x) // uses member x to initialize member y
 
     {}
 
     {}
 
+
   
 
     T& operator=(const T& b)
 
     T& operator=(const T& b)
 
     {
 
     {
Line 127: Line 129:
 
===Defect reports===
 
===Defect reports===
 
{{dr list begin}}
 
{{dr list begin}}
{{dr list item|wg=cwg|dr=760|std=C++98|before=when {{tt|this}} is used in a nested class, it was unspecified whether<br>it is associated with the nested class or the enclosing class|after={{tt|this}} always associates with<br>the innermost nested class,<br>regardless of whether it is in<br>a non-static member function}}
+
{{dr list item|wg=cwg|dr=760|std=C++98|before=when {{c|this}} is used in a nested class, it was<br>unspecified whether it is associated with<br>the nested class or the enclosing class|after={{c|this}} always associates with<br>the innermost nested class,<br>regardless of whether it is in<br>a non-static member function}}
 +
{{dr list item|wg=cwg|dr=2271|std=C++98|before={{c|this}} could be aliased when<br>constructing a non-const object|after=alias is also<br>prohibited in this case}}
 +
{{dr list item|wg=cwg|dr=2869|std=C++98|before=it was unclear whether {{c|this}} could be used in a<br>static member function of a non-associated class|after=made clear}}
 
{{dr list end}}
 
{{dr list end}}
  
 
{{langlinks|de|es|fr|it|ja|pt|ru|zh}}
 
{{langlinks|de|es|fr|it|ja|pt|ru|zh}}

Latest revision as of 01:57, 12 August 2024

 
 
C++ language
General topics
Flow control
Conditional execution statements
if
Iteration statements (loops)
for
range-for (C++11)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications (until C++17*)
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
explicit (C++11)
static

Special member functions
Templates
Miscellaneous
 
 

Contents

[edit] Syntax

this

The expression this is a prvalue expression whose value is the address of the implicit object parameter (object on which the implicit object member function is being called). It can appear in the following contexts:

1) Within the body of any implicit object member function, including member initializer list, and lambda expression body(since C++11).
2) Within the declaration of any implicit object member function anywhere after the (optional) cv-qualifier sequence, including the exception specification and the trailing return type(since C++11).
4) Within capture list of a lambda expression.
(since C++11)

[edit] Explanation

this can only associate with the innermost enclosing class of its appearance, even if the appearance is invalid in the context:

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
                                  // “this” is not associated with Outer
                                  // even if it is inside a member function of Outer
        };
    }
};

The type of this in a member function of class X is X* (pointer to X). If the member function is declared with a cv-qualifier sequence cv, the type of this is cv X* (pointer to identically cv-qualified X). Since constructors and destructors cannot be declared with cv-qualifiers, the type of this in them is always X*, even when constructing or destroying a const object.

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 can be used in the member function of the reference-counting pointer (for example, std::shared_ptr)(since C++11) responsible for decrementing the reference count, when the last reference to the managed object goes out of scope.

class ref
{
    // ...
    void incRef() { ++mnRef; }
    void decRef() { if (--mnRef == 0) delete this; }
};

[edit] Keywords

this

[edit] 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->” is 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
    }
};

[edit] Defect reports

The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

DR Applied to Behavior as published Correct behavior
CWG 760 C++98 when this is used in a nested class, it was
unspecified whether it is associated with
the nested class or the enclosing class
this always associates with
the innermost nested class,
regardless of whether it is in
a non-static member function
CWG 2271 C++98 this could be aliased when
constructing a non-const object
alias is also
prohibited in this case
CWG 2869 C++98 it was unclear whether this could be used in a
static member function of a non-associated class
made clear