C++ Lecture Notes | Pointers, Pointer Arithmetic & this Pointer
ENGINEERING LECTURE NOTES
B.E. / [Link] — Computer Science & Engineering
POINTERS IN C++
Pointers | Pointer Arithmetic | The this Pointer
Subject: Object-Oriented Programming with C++
Year: 2nd / 3rd Year | Academic Year: 2025–2026
Prerequisites: Variables, Data Types, Functions, Arrays, Classes in C++
Department of Computer Science & Engineering | Page
C++ Lecture Notes | Pointers, Pointer Arithmetic & this Pointer
UNIT 1: POINTERS IN C++
1.1 Introduction to Pointers
A pointer is one of the most powerful features of C++. It gives programmers direct access to memory,
enabling dynamic memory management, efficient array and string handling, and the construction of complex
data structures such as linked lists, trees, and graphs. Mastering pointers is essential for systems
programming, embedded development, and high-performance applications.
Definition: A pointer is a variable that stores the memory address of another variable. It 'points to' a
location in memory rather than holding a data value directly.
1.1.1 Why Use Pointers in C++?
• Dynamic memory allocation using new and delete
• Efficient passing of large objects to functions (avoiding costly copies)
• Building dynamic data structures: linked lists, trees, graphs
• Accessing hardware registers in embedded and system-level programming
• Implementing polymorphism and virtual functions via base-class pointers
• Returning multiple values from a function
1.1.2 Memory and Addresses
RAM is organized as a sequence of bytes. Each byte has a unique numeric address. When you declare a
variable in C++, the compiler reserves memory for it and assigns it an address.
Address (hex) Contents Variable / Description
0x1000 42 int a = 42;
0x1004 3.14 float b = 3.14f;
0x1008 0x1000 (address) int *ptr = &a; — ptr stores address
of a
1.2 Declaring and Initializing Pointers
1.2.1 Pointer Declaration Syntax
// Syntax: data_type *pointer_name;
int *iptr; // Pointer to int
float *fptr; // Pointer to float
double *dptr; // Pointer to double
char *cptr; // Pointer to char
bool *bptr; // Pointer to bool
Department of Computer Science & Engineering | Page
C++ Lecture Notes | Pointers, Pointer Arithmetic & this Pointer
Note: The asterisk (*) in a declaration is NOT the dereference operator — it simply tells the
compiler that this variable is a pointer type.
1.2.2 Pointer Initialization Using the Address-of Operator (&)
The & operator returns the memory address of a variable. A pointer is initialized by assigning it an address
using &.
#include <iostream>
using namespace std;
int main() {
int num = 42;
int *ptr = # // ptr stores the address of num
cout << "Value of num : " << num << endl;
cout << "Address of num (&num) : " << &num << endl;
cout << "Value of ptr (address): " << ptr << endl;
cout << "Value at ptr (*ptr) : " << *ptr << endl;
return 0;
}
/* Output:
Value of num : 42
Address of num (&num) : 0x61ff0c
Value of ptr (address): 0x61ff0c
Value at ptr (*ptr) : 42
*/
1.3 Pointer Operators — & and *
Operator Name Purpose Example
& Address-of Returns the memory ptr = &num
address of a variable
* Dereference Accesses the value val = *ptr
stored at the pointer's
address
1.3.1 Modifying a Variable Through a Pointer
int x = 100;
int *p = &x;
*p = 200; // Changes x via the pointer
cout << x; // Output: 200
cout << *p; // Output: 200 (same location)
Department of Computer Science & Engineering | Page
C++ Lecture Notes | Pointers, Pointer Arithmetic & this Pointer
1.4 Types of Pointers in C++
1.4.1 Null Pointer
A null pointer does not point to any valid memory location. In modern C++ (C++11 and later), always use
nullptr — it is type-safe and preferred over NULL or 0.
int *ptr = nullptr; // preferred in C++11+
if (ptr == nullptr) {
cout << "Pointer is null. Cannot dereference!" << endl;
}
Best Practice: Always initialise pointers to nullptr if no address is available. Always check for nullptr
before dereferencing.
1.4.2 Void Pointer (Generic Pointer)
A void* pointer can hold the address of any data type. It must be explicitly cast before dereferencing. It is
commonly used in generic programming and low-level memory functions.
void *vptr;
int a = 10;
float b = 3.14f;
vptr = &a;
cout << *(static_cast<int*>(vptr)) << endl; // 10
vptr = &b;
cout << *(static_cast<float*>(vptr)) << endl; // 3.14
1.4.3 Pointer to Pointer (Double Pointer)
A pointer to pointer stores the address of another pointer, declared with **. It is essential for dynamic 2D
arrays and for modifying a pointer inside a function.
int x = 50;
int *p = &x; // p points to x
int **pp = &p; // pp points to p
cout << x << endl; // 50 direct access
cout << *p << endl; // 50 one level of indirection
cout << **pp << endl; // 50 two levels of indirection
**pp = 99; // modify x through double pointer
cout << x << endl; // 99
1.4.4 Constant Pointer vs Pointer to Constant
int a = 10, b = 20;
// (A) Pointer to constant: cannot change VALUE through pointer
const int *p1 = &a;
// *p1 = 50; // ERROR: value is read-only
p1 = &b; // OK: address can change
// (B) Constant pointer: cannot change ADDRESS stored in pointer
Department of Computer Science & Engineering | Page
C++ Lecture Notes | Pointers, Pointer Arithmetic & this Pointer
int *const p2 = &a;
*p2 = 50; // OK: value can be modified
// p2 = &b; // ERROR: address is fixed
// (C) Constant pointer to constant: nothing can change
const int *const p3 = &a;
// *p3 = 50; // ERROR
// p3 = &b; // ERROR
1.4.5 Wild Pointer and Dangling Pointer
// Wild Pointer: uninitialized pointer (holds garbage address)
int *wild;
// *wild = 10; // UNDEFINED BEHAVIOUR — never do this
// Dangling Pointer: points to freed / destroyed memory
int *dang = new int(5);
delete dang; // memory freed
// *dang = 10; // UNDEFINED BEHAVIOUR
dang = nullptr; // FIX: reset pointer after delete
1.5 Pointers and Arrays
In C++, an array name decays to a constant pointer to its first element. This makes pointers and arrays
interchangeable in many contexts and enables efficient traversal.
#include <iostream>
using namespace std;
int main() {
int arr[] = {10, 20, 30, 40, 50};
int *ptr = arr; // ptr points to arr[0]
// All four expressions below are equivalent:
cout << arr[2] << endl; // 30 subscript on array
cout << ptr[2] << endl; // 30 subscript on pointer
cout << *(arr + 2) << endl; // 30 arithmetic on array name
cout << *(ptr + 2) << endl; // 30 arithmetic on pointer
return 0;
}
1.6 Pointers and Functions
1.6.1 Pass by Pointer (Call by Address)
Passing a pointer allows a function to directly modify the caller's variable. Classic example: swapping two
values.
#include <iostream>
using namespace std;
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
Department of Computer Science & Engineering | Page
C++ Lecture Notes | Pointers, Pointer Arithmetic & this Pointer
int main() {
int x = 10, y = 20;
cout << "Before: x=" << x << ", y=" << y << endl;
swap(&x, &y);
cout << "After : x=" << x << ", y=" << y << endl;
return 0;
}
/* Output:
Before: x=10, y=20
After : x=20, y=10
*/
1.6.2 Returning a Pointer from a Function
// Safe: return pointer to a variable whose lifetime exceeds the call
int* getLarger(int *a, int *b) {
return (*a > *b) ? a : b;
}
int main() {
int x = 15, y = 30;
int *res = getLarger(&x, &y);
cout << "Larger = " << *res << endl; // 30
return 0;
}
Warning: Never return a pointer to a local variable. The local variable is destroyed when the
function returns, leaving a dangling pointer.
1.7 Dynamic Memory Allocation with new / delete
C++ uses new to allocate heap memory at runtime and delete to release it. This is the foundation of dynamic
data structures.
#include <iostream>
using namespace std;
int main() {
// Single object on heap
int *p = new int(100);
cout << *p << endl; // 100
delete p;
p = nullptr;
// Dynamic array on heap
int n = 5;
int *arr = new int[n];
for (int i = 0; i < n; i++)
arr[i] = (i + 1) * 10; // 10 20 30 40 50
for (int i = 0; i < n; i++)
cout << arr[i] << " ";
cout << endl;
delete[] arr; // MUST use delete[] for arrays
arr = nullptr;
return 0;
Department of Computer Science & Engineering | Page
C++ Lecture Notes | Pointers, Pointer Arithmetic & this Pointer
1.8 Pointer to Object
Pointers can point to objects of a class. The arrow operator (->) is used to access class members through a
pointer and is preferred over (*ptr).member.
#include <iostream>
using namespace std;
class Rectangle {
public:
int length, width;
int area() { return length * width; }
};
int main() {
Rectangle r;
[Link] = 5;
[Link] = 3;
Rectangle *ptr = &r;
cout << (*ptr).area() << endl; // 15 via dot on dereferenced pointer
cout << ptr->area() << endl; // 15 via arrow operator (preferred)
cout << ptr->length << endl; // 5
// Dynamic object
Rectangle *rDyn = new Rectangle();
rDyn->length = 8;
rDyn->width = 4;
cout << rDyn->area() << endl; // 32
delete rDyn;
return 0;
}
Department of Computer Science & Engineering | Page
C++ Lecture Notes | Pointers, Pointer Arithmetic & this Pointer
UNIT 2: POINTER ARITHMETIC OPERATIONS
2.1 What is Pointer Arithmetic?
Pointer arithmetic refers to arithmetic operations applied to pointer variables. Unlike ordinary integer
arithmetic, pointer arithmetic is automatically scaled by the size of the data type the pointer points to. This
makes it ideal for traversing arrays and working with contiguous memory blocks efficiently.
Key Rule: Adding 1 to a pointer advances it by sizeof(pointed_type) bytes, NOT by 1 byte. The
compiler handles this scaling transparently.
2.2 Valid Pointer Arithmetic Operations
Operation Allowed? Meaning
ptr + n YES Move n elements forward (address
+= n * sizeof(type))
ptr - n YES Move n elements backward
ptr++ / ++ptr YES Advance to the next element
ptr-- / --ptr YES Move to the previous element
ptr1 - ptr2 YES Number of elements between two
pointers (returns ptrdiff_t)
ptr1 == ptr2 YES Equality comparison of two
addresses
ptr1 < ptr2 YES Ordering comparison (valid within
the same array)
ptr1 + ptr2 NO Adding two pointers is meaningless
and illegal in C++
ptr * n / ptr / n NO Multiplication/Division on pointers
is not allowed
2.3 Size Scaling — How Increment Works
// Sizes (typical 64-bit system): char=1, int=4, float=4, double=8
char *cp = (char*)1000; cp++; // cp = 1001 (moved 1 byte)
int *ip = (int*)1000; ip++; // ip = 1004 (moved 4 bytes)
float *fp = (float*)1000; fp++; // fp = 1004 (moved 4 bytes)
double *dp = (double*)1000; dp++; // dp = 1008 (moved 8 bytes)
Pointer Type sizeof (bytes) ptr + 0 ptr + 1 ptr + 2 ptr + 3
char* 1 1000 1001 1002 1003
int* 4 1000 1004 1008 1012
Department of Computer Science & Engineering | Page
C++ Lecture Notes | Pointers, Pointer Arithmetic & this Pointer
float* 4 1000 1004 1008 1012
double* 8 1000 1008 1016 1024
2.4 Traversing an Array Using Pointer Arithmetic
#include <iostream>
using namespace std;
int main() {
int arr[] = {10, 20, 30, 40, 50};
int n = 5;
int *ptr = arr; // ptr points to arr[0]
// Forward traversal using ptr++
cout << "Forward : ";
for (int i = 0; i < n; i++, ptr++)
cout << *ptr << " ";
cout << endl;
// Reverse traversal using ptr--
ptr = arr + (n - 1); // point to last element
cout << "Reverse : ";
for (int i = 0; i < n; i++, ptr--)
cout << *ptr << " ";
cout << endl;
return 0;
}
/* Output:
Forward : 10 20 30 40 50
Reverse : 50 40 30 20 10
*/
2.5 Pointer Addition and Subtraction with an Integer
#include <iostream>
using namespace std;
int main() {
int arr[] = {100, 200, 300, 400, 500};
int *ptr = arr;
cout << *(ptr + 0) << endl; // 100 arr[0]
cout << *(ptr + 2) << endl; // 300 arr[2]
cout << *(ptr + 4) << endl; // 500 arr[4]
int *ptr2 = arr + 4; // points to arr[4]
cout << ptr2 - ptr << endl; // 4 (4 elements apart)
return 0;
}
Department of Computer Science & Engineering | Page
C++ Lecture Notes | Pointers, Pointer Arithmetic & this Pointer
2.6 Subtracting Two Pointers
Subtracting two pointers gives the number of elements (not bytes) between them. Both pointers must point
into the same array for the result to be well-defined.
int arr[] = {5, 10, 15, 20, 25};
int *p1 = &arr[1]; // points to arr[1]
int *p2 = &arr[4]; // points to arr[4]
ptrdiff_t diff = p2 - p1;
cout << diff << endl; // 3 (indices 4 - 1 = 3 elements apart)
2.7 Comparing Pointers
Pointer comparison using ==, !=, <, >, <=, >= is valid when both pointers point into the same array. This
technique is commonly used for iterator-style loops.
#include <iostream>
using namespace std;
int main() {
int arr[] = {2, 4, 6, 8, 10};
int *start = arr;
int *end = arr + 5; // one-past-the-end (standard idiom)
for (int *p = start; p < end; p++)
cout << *p << " ";
cout << endl;
// Output: 2 4 6 8 10
return 0;
}
2.8 Pointer Arithmetic with 2D Arrays
#include <iostream>
using namespace std;
int main() {
int mat[3][4] = {
{ 1, 2, 3, 4 },
{ 5, 6, 7, 8 },
{ 9, 10, 11, 12 }
};
// mat[i][j] == *(*(mat + i) + j)
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++)
cout << *(*(mat + i) + j) << "\t";
cout << endl;
}
return 0;
}
/* Output:
1 2 3 4
5 6 7 8
9 10 11 12
*/
Department of Computer Science & Engineering | Page
C++ Lecture Notes | Pointers, Pointer Arithmetic & this Pointer
2.9 Common Mistakes in Pointer Arithmetic
Mistake Example Problem
Out-of-bounds access *(ptr + 10) on a 5-element array Undefined behaviour / crash
Adding two pointers ptr1 + ptr2 Illegal — result has no physical
meaning
Cross-array comparison ptr1 < ptr2 (different arrays) Undefined behaviour in C++
Forgetting size scaling Treating ptr+1 as +1 byte Logical error — actually
+sizeof(type) bytes
Not resetting after delete delete p; then *p = 5; Dangling pointer — undefined
behaviour
Exam Tip: In pointer arithmetic the unit of movement is sizeof(pointed_type), not bytes. ptr+n
moves ptr forward by n * sizeof(*ptr) bytes in actual memory.
Department of Computer Science & Engineering | Page
C++ Lecture Notes | Pointers, Pointer Arithmetic & this Pointer
UNIT 3: THE 'this' POINTER IN C++
3.1 Introduction
The this pointer is a special implicit pointer available inside every non-static member function of a class. It
automatically points to the object through which the member function was called. The programmer never
declares or initialises it — the compiler inserts it automatically as a hidden first argument to every non-static
member function call.
Definition: Inside a non-static member function, 'this' is a constant pointer that holds the address of
the calling object. Its type is: ClassName* const this.
3.2 Why Does this Exist?
• Every object has its own data members but shares the same member functions.
• When a member function executes, C++ must know WHICH object's data to access.
• The this pointer is the mechanism that tells the function which object invoked it.
3.3 How the Compiler Uses this Internally
// What you write:
[Link]("Alice");
// What the compiler transforms it into internally:
setName(&obj, "Alice"); // &obj becomes 'this' inside the function
3.4 Basic Example — Observing this
#include <iostream>
using namespace std;
class Demo {
public:
int value;
void show() {
cout << "Object address (this) : " << this << endl;
cout << "Value via this->value : " << this->value << endl;
cout << "Value directly : " << value << endl;
// 'this->value' and 'value' are identical inside a member function
}
};
int main() {
Demo d1, d2;
[Link] = 100;
[Link] = 200;
Department of Computer Science & Engineering | Page
C++ Lecture Notes | Pointers, Pointer Arithmetic & this Pointer
cout << "Address of d1 : " << &d1 << endl;
[Link](); // this == &d1
cout << "Address of d2 : " << &d2 << endl;
[Link](); // this == &d2
return 0;
}
/* Output (addresses are illustrative):
Address of d1 : 0x61ff04
Object address (this) : 0x61ff04
Value via this->value : 100
Value directly : 100
Address of d2 : 0x61ff08
Object address (this) : 0x61ff08
Value via this->value : 200
Value directly : 200
*/
3.5 Use Case 1 — Resolving Name Conflicts (Parameter Shadowing)
When a constructor or setter function parameter has the same name as a data member, the parameter
shadows the member. The this pointer explicitly refers to the data member and resolves the ambiguity.
#include <iostream>
using namespace std;
class Student {
string name;
int rollNo;
public:
// Parameter names are identical to data member names
void setData(string name, int rollNo) {
this->name = name; // this->name refers to the DATA MEMBER
this->rollNo = rollNo; // name refers to the PARAMETER
}
void display() const {
cout << "Name : " << name << endl;
cout << "Roll No : " << rollNo << endl;
}
};
int main() {
Student s;
[Link]("Priya", 101);
[Link]();
return 0;
}
/* Output:
Name : Priya
Roll No : 101
*/
Department of Computer Science & Engineering | Page
C++ Lecture Notes | Pointers, Pointer Arithmetic & this Pointer
3.6 Use Case 2 — Method Chaining via return *this
When a member function returns a reference to the current object (*this), multiple calls can be chained
together in a single statement. This is the Fluent Interface design pattern, widely used in C++ builder
classes, stream operators, and libraries.
#include <iostream>
using namespace std;
class Counter {
int count;
public:
Counter() : count(0) {}
Counter& increment() { count++; return *this; }
Counter& decrement() { count--; return *this; }
Counter& add(int n) { count += n; return *this; }
Counter& reset() { count = 0; return *this; }
void show() { cout << "Count = " << count << endl; }
};
int main() {
Counter c;
// Method chaining — each call returns *this
[Link]().increment().add(5).increment().show();
// Count = 8 (1 + 1 + 5 + 1)
[Link]().add(10).decrement().show();
// Count = 9 (10 - 1)
return 0;
}
3.7 Use Case 3 — Self-Assignment Check in operator=
The this pointer is used to guard against self-assignment in the overloaded assignment operator. Without
this check, assigning an object to itself can cause data corruption or double-free errors.
#include <iostream>
using namespace std;
class Box {
int *data;
public:
Box(int v) { data = new int(v); }
// Copy assignment operator with self-assignment guard
Box& operator=(const Box &other) {
if (this == &other) // self-assignment check
return *this; // nothing to do, return current object
delete data; // free existing resource
data = new int(*[Link]);// deep copy
return *this;
}
void show() const { cout << "Value: " << *data << endl; }
~Box() { delete data; }
};
Department of Computer Science & Engineering | Page
C++ Lecture Notes | Pointers, Pointer Arithmetic & this Pointer
int main() {
Box b1(100), b2(200);
b1 = b2; // normal assignment
[Link](); // Value: 200
b1 = b1; // self-assignment — safe because of the guard
[Link](); // Value: 200
return 0;
}
3.8 Use Case 4 — Comparing Two Objects
#include <iostream>
using namespace std;
class Point {
int x, y;
public:
Point(int x, int y) : x(x), y(y) {}
bool isSameObject(const Point &other) const {
return (this == &other); // true only if same object in memory
}
};
int main() {
Point p1(1, 2), p2(1, 2);
cout << boolalpha;
cout << [Link](p1) << endl; // true (same object)
cout << [Link](p2) << endl; // false (different objects)
return 0;
}
3.9 this in Static vs Non-Static Member Functions
Function Type Has 'this'? Reason
Non-static member function YES Invoked on a specific object; this
identifies it
Static member function NO Belongs to the class, not any
object; called via
ClassName::func()
Constructor YES Called when object is created; this
is the newly created object
Destructor YES Called when object is destroyed;
this is the object being destroyed
Friend function NO Not a member function; no implicit
calling object
class MyClass {
int x = 42;
public:
static void staticFunc() {
Department of Computer Science & Engineering | Page
C++ Lecture Notes | Pointers, Pointer Arithmetic & this Pointer
// cout << this->x; // ERROR: 'this' is unavailable in static functions
cout << "Static function called" << endl;
}
void nonStaticFunc() {
cout << this->x << endl; // OK: this is available
}
};
int main() {
MyClass::staticFunc(); // no object needed
MyClass obj;
[Link](); // this == &obj
return 0;
}
3.10 The this Pointer — Complete Summary
Property Details
Type ClassName* const (const pointer: address of calling
object cannot change)
Availability Only inside non-static member functions (incl.
constructors and destructors)
Points to The specific object through which the member function
was called
Declared by Compiler automatically — never declared explicitly by
the programmer
Primary uses 1. Resolve name conflicts 2. Method chaining (return
*this) 3. Self-assignment guard 4. Object identity
comparison
In static functions NOT available — static functions have no associated
object instance
Exam Tip: Return *this (dereferenced object) when the return type is ClassName& (reference).
Return this (the pointer) when the return type is ClassName*. Mixing these up is a very common
exam mistake.
Department of Computer Science & Engineering | Page
C++ Lecture Notes | Pointers, Pointer Arithmetic & this Pointer
UNIT 4: SUMMARY & QUICK REFERENCE
4.1 Pointer Syntax Quick Reference
Syntax Meaning
int *p Declare p as a pointer to int
p = &x Store address of x in p
*p Dereference p — value at the address stored in p
p++ Advance pointer to next int element (adds sizeof(int)
bytes)
p+n Pointer n elements ahead of p
p1 - p2 Number of elements between p1 and p2 (ptrdiff_t)
int **pp Pointer to pointer to int (double pointer)
nullptr Null pointer constant (C++11 — preferred over NULL)
new int(5) Allocate a single int with value 5 on the heap
delete p Free a single object allocated with new
new int[n] Allocate an array of n ints on the heap
delete[] arr Free an array allocated with new[]
obj->member Access class member through a pointer to an object
4.2 Pointer Arithmetic Quick Reference
Expression Result Type Meaning
ptr + n pointer n elements ahead
ptr - n pointer n elements behind
ptr++ pointer advance by 1 element (post-
increment)
++ptr pointer advance by 1 element (pre-
increment)
p2 - p1 ptrdiff_t number of elements between p1
and p2
p1 == p2 bool do both pointers reference the
same location?
p1 < p2 bool is p1 before p2 in memory? (same-
array pointers only)
4.3 The this Pointer Quick Reference
Scenario Code Pattern Purpose
Department of Computer Science & Engineering | Page
C++ Lecture Notes | Pointers, Pointer Arithmetic & this Pointer
Name conflict resolution this->name = name; Distinguish data member from
parameter of same name
Method chaining return *this; Enable obj.f1().f2().f3() style calls
Self-assignment guard if (this == &other) Prevent crash in overloaded
operator=
Return pointer to self return this; Return the address of the current
object
Object identity check this == &other Verify if two references refer to the
same object
4.4 Review Questions
1. What is the difference between *ptr and &var? Explain with a complete C++ program.
2. Why does ptr++ advance the address by sizeof(type) bytes rather than 1 byte?
3. What is a dangling pointer? How can it be prevented in C++?
4. Write a C++ program that uses pointer arithmetic to compute the sum and average of an array
without using the subscript [] operator.
5. Explain the this pointer with a complete C++ program demonstrating method chaining.
6. Differentiate between const int *p and int *const p with examples.
7. Why is the this pointer not available inside a static member function? Illustrate with code.
8. What is the difference between NULL and nullptr? Which is preferred in modern C++ and why?
9. Write a C++ program using a double pointer (**) to dynamically allocate a 2D array, populate it, print
it, and free the memory correctly.
10. How is the this pointer used to implement a safe copy-assignment operator? Write a complete
program.
4.5 Key Takeaways
• A pointer stores a memory address, not a direct value.
• Always initialise pointers — use nullptr if no valid address is available.
• The & operator gets an address; the * operator dereferences (reads value at) a pointer.
• Pointer arithmetic is automatically scaled by sizeof(pointed_type).
• Subtracting two pointers gives the number of elements between them (not bytes).
• Never add two pointers, multiply, or divide them — these operations are illegal.
• The this pointer is an implicit constant pointer to the calling object, available in all non-static member
functions.
• Return *this for method chaining; use this == &other as a self-assignment guard in operator=.
• Always use delete[] (not delete) for arrays allocated with new[].
• Set pointers to nullptr immediately after delete to avoid dangling pointer bugs.
Final Note: Pointers are the foundation of C++ memory management, dynamic data structures, and
polymorphism. A strong understanding of pointers is critical for advanced topics including operating
systems, compilers, embedded systems, data structures, and competitive programming.
Department of Computer Science & Engineering | Page