this pointer in C++ programming with some example code

The blog post explains “this pointer in C++”. Also, it explains some important points including the places where we need to use “this pointer”. It is my belief you will learn a lot from this blog post.

So let’s first understand this pointer. A “this pointer” is a type of pointer which accessible only within the nonstatic member functions of a class, struct, or union type.

Basically, the keyword ‘this’ is a prvalue (“pure” rvalues) expression, in the body of a non-static member function. The value of ‘this pointer’ is the address of the object for which the function is called.

Note: “this pointer” is not available in static member functions.

Also, we need to remember that “this pointer” isn’t part of the object itself. It’s not reflected in the result of a sizeof statement on the object. When a nonstatic member function is called for an object, the compiler passes the object’s address to the function as a hidden argument.

Let’s see an example, suppose that we create an object named testObj of class Test, and class Test has a nonstatic member function void value(int a).

//class
class Test
{
    //member variable
    int m_data;
public:
    //non-static member function
    void value(int a)
    {
        m_data = a;
    }
};

If you call the function testObj.value(2), the compiler passes the object’s address to the function as a hidden argument (this keyword). So, when we call value(2), we are actually calling value(&testObj,2).

//non-static member function calling
testObj.value(2);

can be interpreted as:

value(&testObj,2);

 

Important points related to this pointer in C++

Now it’s time to see some important points related to this pointer. We will also see where we should use this pointer in code.

1. In C++, “this” keyword is a prvalue expression. Which means “this pointer” is nonmodifiable, and assignment to this pointer is not allowed. ( Note: Earlier implementations of C++ allowed assignment to this).

2. “this pointer” isn’t part of the object itself. It’s not reflected in the result of a sizeof statement on the object. 

3. Friend functions do not have “this pointer”, because friends are not members of a class.

4. Nonstatic member functions of a class, struct, or union type only has the this pointer.

5. The type of this pointer in a member function of a class X is X*.

6. 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*.

class X
{
    void test() const
    {
        // Type of this is const X*
    }
};


class X
{
    void test() volatile
    {
        // Type of this is volatile X*
    }
};


class X
{
    void test() const volatile
    {
        // Type of this is const volatile X*
    }
};

7. this pointer mostly use implicitly. But it’s legal to use this pointer explicitly when referring to members of the class. Let’s see an example,

class Test
{
    //member variable
    int m_data;
    
public:
    //non-static member function
    void value(int a);
};


void Test::value( int a )
{
    m_data = a;            // These three statements
    this->m_data = a;      // are equivalent
    (*this).m_data = a;
}

Thus in a const member function, the object for which the function is called is accessed through a const access path. Let’s see an example,

class Test
{
    int m_data;
public:
    //constructor
    Test():m_data(0)
    {

    }
    //non-const member function
    int g()
    {
        return m_data++;
    }

    //const member function
    int h() const
    {
        return m_data++;    // error
    }
};

The m_data++ in the body of Test::h is ill-formed because it tries to modify (a part of) the object for which Test::h() is called. This is not allowed in a const member function because this is a pointer to const( type of this pointer is const Test *)

8. When the local variable’s name is the same as the member’s name, then to avoid ambiguity we can use “this pointer”. 

#include 
using namespace std;


//class
class Test
{
    //member variable
    int m;
public:
    //non-static member function
    void value(int m)
    {
        // The 'this' pointer is used to
        //retrieve the object's m
        this->m = m;
    }

    void print()
    {
        cout << "m = " << m << endl;
    }
};


int main()
{
    Test testObj;

    testObj.value(6);

    testObj.print();

    return 0;
}

Output: m = 6

9. “this pointer” is also used to guard against self-reference. See the below expression.

// do not execute in cases of self-reference
if (&Object != this) 
{

}


10. Sometimes we use the expression *this to return the current object from a member function.

Test& Test::testFun ()
{
    // Some processing
    return *this;
}

If you already know how to program and just want to learn C++, you can start with the C++ Fundamentals course. The good thing is that TRIAL IS FREE

Duration: Approx. 43 hours
Rating: 4.6

Now let’s see a C++ example code where I am using this pointer in an overloaded assignment operator. In the overloaded assignment operator function, I have also used this pointer as a guard against self-reference.

Basically, In this example code, I am creating two test objects testBuf1 and testBuf2 of the class Buf. Further, I am assigning the testBuf2 to testBuf1 and displaying the testBuf1 buffer.

#include <iostream>
#include <string.h>

using namespace std;


//class Buf
class Buf
{
public:
    Buf( const char* szBuffer);
    ~Buf();
    Buf& operator=( const Buf & );
    void Display()
    {
        cout << m_buffer << endl;
    }

private:
    //private members variable
    char*   m_buffer;
    size_t  m_sizeOfBuffer;
};


//constructor
Buf::Buf(const char* szBuffer)
{
    //adding 1 to account for a NULL terminator
    size_t sizeOfBuffer = strlen(szBuffer) + 1;

    //allocate the memory
    m_buffer = new char[sizeOfBuffer];
    if (m_buffer)
    {
        //copy string in member char buffer
        strncpy(m_buffer, szBuffer,sizeOfBuffer);
        m_sizeOfBuffer = sizeOfBuffer;
    }
}


//destructor
Buf::~Buf()
{
    if (m_buffer)
    {
        delete [] m_buffer;
    }
}

//assignment operator
Buf& Buf::operator=( const Buf &otherbuf )
{
    if( &otherbuf != this )
    {
        if (m_buffer)
        {
            delete [] m_buffer;
        }

        m_sizeOfBuffer =  strlen( otherbuf.m_buffer ) + 1;
        m_buffer = new char[m_sizeOfBuffer];
        strncpy(m_buffer, otherbuf.m_buffer,m_sizeOfBuffer);
    }
    return *this;
}

int main()
{
    Buf testBuf1("Aticleworld");
    Buf testBuf2("Amlendra");

    // Display Aticleworld
    testBuf1.Display();

    // assignment operator
    testBuf1 = testBuf2;

    // Display Amlendra
    testBuf1.Display();

    return 0;
}

Output:

Aticleworld
Amlendra

You can check MCQs on this pointer.