When should I make explicit use of the `this` pointer?

When should I explicitly write this->member in a method of
a class?

7

Usually, you do not have to, this-> is implied.

Sometimes, there is a name ambiguity, where it can be used to disambiguate class members and local variables. However, here is a completely different case where this-> is explicitly required.

Consider the following code:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>template<class T>
struct A {
T i;
};
template<class T>
struct B : A<T> {
T foo() {
return this->i; //standard accepted by all compilers
//return i; //clang and gcc will fail
//clang 13.1.6: use of undeclared identifier 'i'
//gcc 11.3.0: 'i' was not declared in this scope
//Microsoft C++ Compiler 2019 will accept it
}
};
int main() {
B<int> b;
b.foo();
}
</code>
<code>template<class T> struct A { T i; }; template<class T> struct B : A<T> { T foo() { return this->i; //standard accepted by all compilers //return i; //clang and gcc will fail //clang 13.1.6: use of undeclared identifier 'i' //gcc 11.3.0: 'i' was not declared in this scope //Microsoft C++ Compiler 2019 will accept it } }; int main() { B<int> b; b.foo(); } </code>
template<class T>
struct A {
   T i;
};

template<class T>
struct B : A<T> {
    T foo() {
        return this->i; //standard accepted by all compilers 
        //return i; //clang and gcc will fail
        //clang 13.1.6: use of undeclared identifier 'i'
        //gcc 11.3.0: 'i' was not declared in this scope
        //Microsoft C++ Compiler 2019 will accept it
    }

};

int main() {
    B<int> b;
    b.foo();
}

If you omit this->, some compilers do not know how to treat i. In order to tell it that i is indeed a member of A<T>, for any T, the this-> prefix is required.

Note: it is possible to still omit this-> prefix by using:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>template<class T>
struct B : A<T> {
int foo() {
return A<T>::i; // explicitly refer to a variable in the base class
//where 'i' is now known to exist
}
};
</code>
<code>template<class T> struct B : A<T> { int foo() { return A<T>::i; // explicitly refer to a variable in the base class //where 'i' is now known to exist } }; </code>
template<class T>
struct B : A<T> {
    int foo() {
        return A<T>::i; // explicitly refer to a variable in the base class 
        //where 'i' is now known to exist
    }

};

5

If you declare a local variable in a method with the same name as an existing member, you will have to use this->var to access the class member instead of the local variable.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>#include <iostream>
using namespace std;
class A
{
public:
int a;
void f() {
a = 4;
int a = 5;
cout << a << endl;
cout << this->a << endl;
}
};
int main()
{
A a;
a.f();
}
</code>
<code>#include <iostream> using namespace std; class A { public: int a; void f() { a = 4; int a = 5; cout << a << endl; cout << this->a << endl; } }; int main() { A a; a.f(); } </code>
#include <iostream>
using namespace std;
class A
{
    public:
        int a;

        void f() {
            a = 4;
            int a = 5;
            cout << a << endl;
            cout << this->a << endl;
        }
};

int main()
{
    A a;
    a.f();
}

prints:

5
4

2

There are several reasons why you might need to use this pointer explicitly.

  • When you want to pass a reference to your object to some function.
  • When there is a locally declared object with the same name as the member object.
  • When you’re trying to access members of dependent base classes.
  • Some people prefer the notation to visually disambiguate member accesses in their code.

Although I usually don’t particular like it, I’ve seen others use this-> simply to get help from intellisense!

1

There are few cases where using this must be used, and there are others where using the this pointer is one way to solve a problem.

  1. Alternatives Available: To resolve ambiguity between local variables and class members, as illustrated by @ASk.

  2. No Alternative: To return a pointer or reference to this from a member function. This is frequently done (and should be done) when overloading operator+, operator-, operator=, etc:

    Plain text
    Copy to clipboard
    Open code in new window
    EnlighterJS 3 Syntax Highlighter
    <code> class Foo
    {
    Foo& operator=(const Foo& rhs)
    {
    return * this;
    }
    };
    </code>
    <code> class Foo { Foo& operator=(const Foo& rhs) { return * this; } }; </code>
     class Foo
     {
       Foo& operator=(const Foo& rhs)
       {
         return * this;
       }
     };
    

    Doing this permits an idiom known as “method chaining”, where you perform several operations on an object in one line of code. Such as:

    Plain text
    Copy to clipboard
    Open code in new window
    EnlighterJS 3 Syntax Highlighter
    <code> Student st;
    st.SetAge (21).SetGender (male).SetClass ("C++ 101");
    </code>
    <code> Student st; st.SetAge (21).SetGender (male).SetClass ("C++ 101"); </code>
     Student st;
     st.SetAge (21).SetGender (male).SetClass ("C++ 101");
    

    Some consider this concise, others consider it an abomination. Count me in the latter group.

  3. No Alternative: To resolve names in dependant types. This comes up when using templates, as in this example:

    Plain text
    Copy to clipboard
    Open code in new window
    EnlighterJS 3 Syntax Highlighter
    <code> #include <iostream>
    template <typename Val>
    class ValHolder
    {
    private:
    Val mVal;
    public:
    ValHolder (const Val& val)
    :
    mVal (val)
    {
    }
    Val& GetVal() { return mVal; }
    };
    template <typename Val>
    class ValProcessor
    :
    public ValHolder <Val>
    {
    public:
    ValProcessor (const Val& val)
    :
    ValHolder <Val> (val)
    {
    }
    Val ComputeValue()
    {
    // int ret = 2 * GetVal(); // ERROR: No member 'GetVal'
    int ret = 4 * this->GetVal(); // OK -- this tells compiler to examine dependant type (ValHolder)
    return ret;
    }
    };
    int main()
    {
    ValProcessor <int> proc (42);
    const int val = proc.ComputeValue();
    std::cout << val << "n";
    }
    </code>
    <code> #include <iostream> template <typename Val> class ValHolder { private: Val mVal; public: ValHolder (const Val& val) : mVal (val) { } Val& GetVal() { return mVal; } }; template <typename Val> class ValProcessor : public ValHolder <Val> { public: ValProcessor (const Val& val) : ValHolder <Val> (val) { } Val ComputeValue() { // int ret = 2 * GetVal(); // ERROR: No member 'GetVal' int ret = 4 * this->GetVal(); // OK -- this tells compiler to examine dependant type (ValHolder) return ret; } }; int main() { ValProcessor <int> proc (42); const int val = proc.ComputeValue(); std::cout << val << "n"; } </code>
     #include <iostream>
    
    
     template <typename Val>
     class ValHolder
     {
     private:
       Val mVal;
     public:
       ValHolder (const Val& val)
       :
         mVal (val)
       {
       }
       Val& GetVal() { return mVal; }
     };
    
     template <typename Val>
     class ValProcessor
     :
       public ValHolder <Val>
     {
     public:
       ValProcessor (const Val& val)
       :
         ValHolder <Val> (val)
       {
       }
    
       Val ComputeValue()
       {
     //    int ret = 2 * GetVal();  // ERROR:  No member 'GetVal'
         int ret = 4 * this->GetVal();  // OK -- this tells compiler to examine dependant type (ValHolder)
         return ret;
       }
     };
    
     int main()
     {
       ValProcessor <int> proc (42);
       const int val = proc.ComputeValue();
       std::cout << val << "n";
     }
    
  4. Alternatives Available: As a part of coding style, to document which variables are member variables as opposed to local variables. I prefer a different naming scheme where member variables can never have the same name as locals. Currently I’m using mName for members and name for locals.

1

  1. Where a member variable would be hidden by
    a local variable
  2. If you just want
    to make it explictly clear that you
    are calling an instance method/variable

Some coding standards use approach (2) as they claim it makes the code easier to read.

Example:

Assume MyClass has a member variable called ‘count’

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>void MyClass::DoSomeStuff(void)
{
int count = 0;
.....
count++;
this->count = count;
}
</code>
<code>void MyClass::DoSomeStuff(void) { int count = 0; ..... count++; this->count = count; } </code>
void MyClass::DoSomeStuff(void)
{
   int count = 0;

   .....
   count++;
   this->count = count;
}

One other case is when invoking operators. E.g. instead of

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>bool Type::operator!=(const Type& rhs)
{
return !operator==(rhs);
}
</code>
<code>bool Type::operator!=(const Type& rhs) { return !operator==(rhs); } </code>
bool Type::operator!=(const Type& rhs)
{
    return !operator==(rhs);
}

you can say

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>bool Type::operator!=(const Type& rhs)
{
return !(*this == rhs);
}
</code>
<code>bool Type::operator!=(const Type& rhs) { return !(*this == rhs); } </code>
bool Type::operator!=(const Type& rhs)
{
    return !(*this == rhs);
}

Which might be more readable. Another example is the copy-and-swap:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>Type& Type::operator=(const Type& rhs)
{
Type temp(rhs);
temp.swap(*this);
}
</code>
<code>Type& Type::operator=(const Type& rhs) { Type temp(rhs); temp.swap(*this); } </code>
Type& Type::operator=(const Type& rhs)
{
    Type temp(rhs);
    temp.swap(*this);
}

I don’t know why it’s not written swap(temp) but this seems to be common.

1

The other uses for this (as I thought when I read the summary and half the question… .), disregarding (bad) naming disambiguation in other answers, are if you want to cast the current object, bind it in a function object or use it with a pointer-to-member.

Casts

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>void Foo::bar() {
misc_nonconst_stuff();
const Foo* const_this = this;
const_this->bar(); // calls const version
dynamic_cast<Bar*>(this)->bar(); // calls specific virtual function in case of multi-inheritance
}
void Foo::bar() const {}
</code>
<code>void Foo::bar() { misc_nonconst_stuff(); const Foo* const_this = this; const_this->bar(); // calls const version dynamic_cast<Bar*>(this)->bar(); // calls specific virtual function in case of multi-inheritance } void Foo::bar() const {} </code>
void Foo::bar() {
    misc_nonconst_stuff();
    const Foo* const_this = this;
    const_this->bar(); // calls const version

    dynamic_cast<Bar*>(this)->bar(); // calls specific virtual function in case of multi-inheritance
} 

void Foo::bar() const {}

Binding

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>void Foo::baz() {
for_each(m_stuff.begin(), m_stuff.end(), bind(&Foo:framboozle, this, _1));
for_each(m_stuff.begin(), m_stuff.end(), [this](StuffUnit& s) { framboozle(s); });
}
void Foo::framboozle(StuffUnit& su) {}
std::vector<StuffUnit> m_stuff;
</code>
<code>void Foo::baz() { for_each(m_stuff.begin(), m_stuff.end(), bind(&Foo:framboozle, this, _1)); for_each(m_stuff.begin(), m_stuff.end(), [this](StuffUnit& s) { framboozle(s); }); } void Foo::framboozle(StuffUnit& su) {} std::vector<StuffUnit> m_stuff; </code>
void Foo::baz() {
     for_each(m_stuff.begin(), m_stuff.end(),  bind(&Foo:framboozle, this, _1));        
     for_each(m_stuff.begin(), m_stuff.end(), [this](StuffUnit& s) { framboozle(s); });         
} 

void Foo::framboozle(StuffUnit& su) {}

std::vector<StuffUnit> m_stuff;

ptr-to-member

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>void Foo::boz() {
bez(&Foo::bar);
bez(&Foo::baz);
}
void Foo::bez(void (Foo::*func_ptr)()) {
for (int i=0; i<3; ++i) {
(this->*func_ptr)();
}
}
</code>
<code>void Foo::boz() { bez(&Foo::bar); bez(&Foo::baz); } void Foo::bez(void (Foo::*func_ptr)()) { for (int i=0; i<3; ++i) { (this->*func_ptr)(); } } </code>
void Foo::boz() {
    bez(&Foo::bar);
    bez(&Foo::baz);
} 

void Foo::bez(void (Foo::*func_ptr)()) {
    for (int i=0; i<3; ++i) {
        (this->*func_ptr)();
    }
}

Hope it helps to show other uses of this than just this->member.

You only have to use this-> if you have a symbol with the same name in two potential namespaces. Take for example:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>class A {
public:
void setMyVar(int);
void doStuff();
private:
int myVar;
}
void A::setMyVar(int myVar)
{
this->myVar = myVar; // <- Interesting point in the code
}
void A::doStuff()
{
int myVar = ::calculateSomething();
this->myVar = myVar; // <- Interesting point in the code
}
</code>
<code>class A { public: void setMyVar(int); void doStuff(); private: int myVar; } void A::setMyVar(int myVar) { this->myVar = myVar; // <- Interesting point in the code } void A::doStuff() { int myVar = ::calculateSomething(); this->myVar = myVar; // <- Interesting point in the code } </code>
class A {
public:
   void setMyVar(int);
   void doStuff();

private:
   int myVar;
}

void A::setMyVar(int myVar)
{
  this->myVar = myVar;  // <- Interesting point in the code
}

void A::doStuff()
{
  int myVar = ::calculateSomething();
  this->myVar = myVar; // <- Interesting point in the code
}

At the interesting points in the code, referring to myVar will refer to the local (parameter or variable) myVar. In order to access the class member also called myVar, you need to explicitly use “this->”.

1

You need to use this to disambiguate between a parameters/local variables and member variables.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>class Foo
{
protected:
int myX;
public:
Foo(int myX)
{
this->myX = myX;
}
};
</code>
<code>class Foo { protected: int myX; public: Foo(int myX) { this->myX = myX; } }; </code>
class Foo
{
protected:
  int myX;

public:
  Foo(int myX)
  {
    this->myX = myX; 
  }
};

1

The main (or I can say, the only) purpose of this pointer is that it points to the object used to invoke a member function.

Base on this purpose, we can have some cases that only using this pointer can solve the problem.

For example, we have to return the invoking object in a member function with argument is an same class object:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>class human {
...
human & human::compare(human & h){
if (condition)
return h; // argument object
else
return *this; // invoking object
}
};
</code>
<code>class human { ... human & human::compare(human & h){ if (condition) return h; // argument object else return *this; // invoking object } }; </code>
class human {

... 

human & human::compare(human & h){
    if (condition)
        return h;       // argument object
    else 
        return *this;   // invoking object
    }
};

I found another interesting case of explicit usage of the “this” pointer in the Effective C++ book.

For example, say you have a const function like

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code> unsigned String::length() const
</code>
<code> unsigned String::length() const </code>
  unsigned String::length() const

You don’t want to calculate String’s length for each call, hence you want to cache it doing something like

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code> unsigned String::length() const
{
if(!lengthInitialized)
{
length = strlen(data);
lengthInitialized = 1;
}
}
</code>
<code> unsigned String::length() const { if(!lengthInitialized) { length = strlen(data); lengthInitialized = 1; } } </code>
  unsigned String::length() const
  {
    if(!lengthInitialized)
    {
      length = strlen(data);
      lengthInitialized = 1;
    }
  }

But this won’t compile – you are changing the object in a const function.

The trick to solve this requires casting this to a non-const this:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code> String* const nonConstThis = (String* const) this;
</code>
<code> String* const nonConstThis = (String* const) this; </code>
  String* const nonConstThis = (String* const) this;

Then, you’ll be able to do in above

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code> nonConstThis->lengthInitialized = 1;
</code>
<code> nonConstThis->lengthInitialized = 1; </code>
  nonConstThis->lengthInitialized = 1;

2

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật