BogoToBogo
  • Home
  • About
  • Big Data
  • Machine Learning
  • AngularJS
  • Python
  • C++
  • go
  • DevOps
  • Kubernetes
  • Algorithms
  • More...
    • Qt 5
    • Linux
    • FFmpeg
    • Matlab
    • Django 1.8
    • Ruby On Rails
    • HTML5 & CSS

C++ Tutorial - The this Pointer - 2020

cplusplus_icon.png




Bookmark and Share





bogotobogo.com site search:




The this Pointer

When I started leaning C++, one of the big questions was, - What the heck is this this?


As it turned out this is a special kind of pointer.

The this pointer stores the address of the class instance, to enable pointer access of the members to the member functions of the class. There is a secret not obvious to the new programmers - this pointer holds the key to the question:
How does C++ know which object it was called on?
The answer is that C++ has a hidden pointer named this!

Suppose that we create an object named objA of class A, and class A has a nonstatic member function void f(). If you call the function objA.f(), the keyword this in the body of f() stores the address of objA. The type of the this pointer for a member function of a class type A, is A* const.

So, when we call f(), we are actually calling f(&objA;). Since C++ converts the function call, it also needs to convert the function itself:

void A::f() { }

converted internally to:

void A::f(A* const this);

C++ has added a new parameter to the function. The added parameter is a pointer to the class object the class function is working with. It is always named this. The this pointer is a hidden pointer inside every class member function that points to the class object. As a result, an object's this pointer is not part of the object itself; it is not reflected in the result of a sizeof statement on the object. Instead, when a nonstatic member function is called for an object, the address of the object is passed by the compiler as a hidden argument to the function.

Let's take a look at a specific example. It's simple calculator code for something like Amazon.com's Cart and CheckOut.

#include <iostream>

class Cart {  
private:  
	int total;    
public:  
	Cart(int item){
		this->total = item;
	}  
	Cart& addItem(int itemPrice) { 
		total += itemPrice;
		return *this;
	}
	void checkOut() {
		std::cout << "total: " << total << " $\n";
	}
}; 

int main()
{
	Cart myCart(0);
	myCart.addItem(100);
	myCart.checkOut();
}

In the code, when we call

myCart.addItem(100);

we are actually calling a function converted by compiler:

myCart.addItem(&myCart;, 100);

The function itself should be converted from

Cart& addItem(int itemPrice) { 
	total += itemPrice;
	return *this;
}
to
Cart& addItem(myCart* const this, int itemPrice) { 
	this->total += itemPrice;
	return *this;
}

Note that the following expressions are equivalent:

this->total;
(*this).total;

The fact that the return type is a reference means that the returned object is the invoking object itself (myCart) rather than a copy passed by the return mechanism.

In the main(), we did not utilize the returned object. If we modify the main a little (chain of addItem), we can add as many items we want. Here is a new code.

#include <iostream>

class Cart {  
private:  
	int total;    
public:  
	Cart(int item){
		this->total = item;
	}  
	Cart& addItem(int itemPrice) { 
		total += itemPrice;
		return *this;
	}
	void checkOut() {
		std::cout << "total: " << total << " $\n";
	}
}; 

int main()
{
	Cart myCart(0);
	myCart.addItem(100).addItem(200).addItem(300);
	myCart.checkOut();
}

Output is simple:

total: 600 $



Constness of this Pointer

It's worth noting that this is a const pointer: we can change the value of the object it points to, but we cannot make it point to something else! So, we cannot declare the this pointer or make assignments to it.

If the member function is declared with the const qualifier, the type of the this pointer for that member function for class A, is const A* const.

A const this pointer can be used only with const member functions. Data members of the class will be constant within that function. The function is still able to change the value, but requires a const_cast to do so:

void A::f() const{    
member = 2010:			// illegal    
const_cast <int&> (member) =2010;	// a bad practice but legal 
}

A better technique would be to declare member mutable. If the member function is declared with the volatile qualifier, the type of the this pointer for that member function for class A is volatile A* const. For example, the compiler will not allow the following:

class A {
  int n;
  int f() const { return n++; }
};

The compiler will not allow the statement n++ in the body of function f(). In the function f(), the this pointer is of type A* const. The function f() is trying to modify part of the object to which this points.

The this pointer is also used to guard against self-reference:

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



Argument Matching

Depending on whether they are declared as static, class member functions are treated differently. Since nonstatic functions have an implicit argument that supplies the this pointer, nonstatic functions are considered to have one more argument than static functions; otherwise, they are declared identically.

These nonstatic member functions require that the implied this pointer match the object type through which the function is being called, or, for overloaded operators, they require that the first argument match the object on which the operator is being applied.

Unlike other arguments in overloaded functions, no temporary objects are introduced and no conversions are attempted when trying to match the this pointer argument.

When the -> member-selection operator is used to access a member function, the this pointer argument has a type of class-name * const. If the members are declared as const or volatile, the types are const class-name* const and volatile class-name * const, respectively.

The . member-selection operator works exactly the same way, except that an implicit & (address-of) operator is prefixed to the object name.

If we write the following code:

obj.name

The compiler internally treats it like this:

(&obj;)->name


Using this in the constructor

Are we able to use this inside the constructor?

Quick answer is yes. We are asking this question because we think at the time of using this pointer in a constructor, the object is not fully formed yet. However, we can use this in the constructor (in the {body} and even in the initialization list) if we are careful enough.

Here is something that always works: the {body} of a constructor (or a function called from the constructor) can reliably access the data members declared in a base class and/or the data members declared in the constructor's own class. This is because all those data members are guaranteed to have been fully constructed by the time the constructor's {body} starts executing.

But things get complicated when we have to deal with virtual method.........



Deleting this Pointer

Deleting this?
No creative mind would do it. Only the destructive mind would try.

Anyway, I think it won't work. Even in the destructor. It may be like deleting null pointer. I tried with my Visual Studio, I couldn't get it done without a crash.

The fundamental issue is how we can figure it out where this is on the heap memory since we can use delete only on an object which is on the heap (free store) area.

In his book, "More Effective C++ 35 New Ways ...", Scott Meyers concludes, "After all, if we could tell when an address is on the heap, we could surely tell when an address is not on the heap. But we can't, so we can't. Oh Well.



DuckYouSanJuMok2





Ph.D. / Golden Gate Ave, San Francisco / Seoul National Univ / Carnegie Mellon / UC Berkeley / DevOps / Deep Learning / Visualization

YouTubeMy YouTube channel

Sponsor Open Source development activities and free contents for everyone.

Thank you.

- K Hong






Sponsor Open Source development activities and free contents for everyone.

Thank you.

- K Hong






C++ Tutorials

C++ Home

Algorithms & Data Structures in C++ ...

Application (UI) - using Windows Forms (Visual Studio 2013/2012)

auto_ptr

Binary Tree Example Code

Blackjack with Qt

Boost - shared_ptr, weak_ptr, mpl, lambda, etc.

Boost.Asio (Socket Programming - Asynchronous TCP/IP)...

Classes and Structs

Constructor

C++11(C++0x): rvalue references, move constructor, and lambda, etc.

C++ API Testing

C++ Keywords - const, volatile, etc.

Debugging Crash & Memory Leak

Design Patterns in C++ ...

Dynamic Cast Operator

Eclipse CDT / JNI (Java Native Interface) / MinGW

Embedded Systems Programming I - Introduction

Embedded Systems Programming II - gcc ARM Toolchain and Simple Code on Ubuntu and Fedora

Embedded Systems Programming III - Eclipse CDT Plugin for gcc ARM Toolchain

Exceptions

Friend Functions and Friend Classes

fstream: input & output

Function Overloading

Functors (Function Objects) I - Introduction

Functors (Function Objects) II - Converting function to functor

Functors (Function Objects) - General



Git and GitHub Express...

GTest (Google Unit Test) with Visual Studio 2012

Inheritance & Virtual Inheritance (multiple inheritance)

Libraries - Static, Shared (Dynamic)

Linked List Basics

Linked List Examples

make & CMake

make (gnu)

Memory Allocation

Multi-Threaded Programming - Terminology - Semaphore, Mutex, Priority Inversion etc.

Multi-Threaded Programming II - Native Thread for Win32 (A)

Multi-Threaded Programming II - Native Thread for Win32 (B)

Multi-Threaded Programming II - Native Thread for Win32 (C)

Multi-Threaded Programming II - C++ Thread for Win32

Multi-Threaded Programming III - C/C++ Class Thread for Pthreads

MultiThreading/Parallel Programming - IPC

Multi-Threaded Programming with C++11 Part A (start, join(), detach(), and ownership)

Multi-Threaded Programming with C++11 Part B (Sharing Data - mutex, and race conditions, and deadlock)

Multithread Debugging

Object Returning

Object Slicing and Virtual Table

OpenCV with C++

Operator Overloading I

Operator Overloading II - self assignment

Pass by Value vs. Pass by Reference

Pointers

Pointers II - void pointers & arrays

Pointers III - pointer to function & multi-dimensional arrays

Preprocessor - Macro

Private Inheritance

Python & C++ with SIP

(Pseudo)-random numbers in C++

References for Built-in Types

Socket - Server & Client

Socket - Server & Client 2

Socket - Server & Client 3

Socket - Server & Client with Qt (Asynchronous / Multithreading / ThreadPool etc.)

Stack Unwinding

Standard Template Library (STL) I - Vector & List

Standard Template Library (STL) II - Maps

Standard Template Library (STL) II - unordered_map

Standard Template Library (STL) II - Sets

Standard Template Library (STL) III - Iterators

Standard Template Library (STL) IV - Algorithms

Standard Template Library (STL) V - Function Objects

Static Variables and Static Class Members

String

String II - sstream etc.

Taste of Assembly

Templates

Template Specialization

Template Specialization - Traits

Template Implementation & Compiler (.h or .cpp?)

The this Pointer

Type Cast Operators

Upcasting and Downcasting

Virtual Destructor & boost::shared_ptr

Virtual Functions



Programming Questions and Solutions ↓

Strings and Arrays

Linked List

Recursion

Bit Manipulation

Small Programs (string, memory functions etc.)

Math & Probability

Multithreading

140 Questions by Google



Qt 5 EXPRESS...

Win32 DLL ...

Articles On C++

What's new in C++11...

C++11 Threads EXPRESS...

Go Tutorial

OpenCV...








Contact

BogoToBogo
contactus@bogotobogo.com

Follow Bogotobogo

About Us

contactus@bogotobogo.com

YouTubeMy YouTube channel
Pacific Ave, San Francisco, CA 94115

Pacific Ave, San Francisco, CA 94115

Copyright © 2024, bogotobogo
Design: Web Master