Lesson 42 of 60 – Pointers in C++
70%

Pointers in C++

A pointer is a variable that stores the memory address of another variable. Pointers are an important feature of C++ and are commonly used with arrays, functions, dynamic memory, and data structures.

Note: A pointer stores an address, while the dereference operator * is used to access the value stored at that address.

1. What is a Pointer?

A pointer is a variable that stores the memory address of another variable.

int number = 10;

int* ptr = &number;

Here, ptr stores the address of number.

2. Why Use Pointers?

Pointers are useful in many areas of C++ programming.

  • Access memory addresses.
  • Work with arrays.
  • Pass data efficiently to functions.
  • Modify variables through their addresses.
  • Work with dynamic memory.
  • Build data structures such as linked lists and trees.

3. Declaring a Pointer

The basic syntax for declaring a pointer is:

dataType* pointerName;

Example:

int* ptr;

This declares ptr as a pointer to an integer.

4. The Address-of Operator &

The & operator can be used to get the memory address of a variable.

int number = 10;

std::cout << &number;

The output will be a memory address. The exact address can differ each time the program runs.

5. Storing an Address in a Pointer

int number = 10;

int* ptr = &number;

The expression &number gets the address of number, and that address is stored in ptr.

6. The Dereference Operator *

The * operator can be used to access the value stored at the address held by a pointer.

int number = 10;

int* ptr = &number;

std::cout << *ptr;

Output:

10

7. Address and Value

int number = 50;

int* ptr = &number;

std::cout << "Value = "
          << number
          << std::endl;

std::cout << "Address = "
          << &number
          << std::endl;

std::cout << "Pointer = "
          << ptr
          << std::endl;

std::cout << "Value through pointer = "
          << *ptr;

The pointer and &number represent the same address, while *ptr accesses the value stored there.

8. Changing a Value Through a Pointer

A pointer can be used to modify the value of the variable it points to.

int number = 10;

int* ptr = &number;

*ptr = 100;

std::cout << number;

Output:

100

Changing *ptr changes the original variable.

9. Pointer Data Type

A pointer should normally point to an object of a compatible type.

int number = 10;
double price = 25.5;

int* intPtr = &number;
double* doublePtr = &price;

The pointer type describes the type of object it points to.

10. Pointer to a Character

char letter = 'A';

char* ptr = &letter;

std::cout << *ptr;

Output:

A

11. Pointer to a Double

double price = 99.50;

double* ptr = &price;

std::cout << *ptr;

The pointer stores the address of the double variable.

12. Null Pointer

A null pointer does not point to a valid object. In modern C++, use nullptr to represent a null pointer.

int* ptr = nullptr;

Before dereferencing a pointer that may be null, check it first.

if (ptr != nullptr) {

    std::cout << *ptr;
}

13. Pointer Initialization

A pointer should be initialized before it is used.

int number = 20;

int* ptr = &number;

If a pointer does not currently point to an object, initialize it with nullptr rather than leaving it uninitialized.

14. Pointer to Pointer

A pointer can store the address of another pointer. This is called a pointer to pointer.

int number = 10;

int* ptr = &number;

int** ptr2 = &ptr;

std::cout << **ptr2;

Output:

10

15. Pointer and Arrays

The name of a built-in array can be used in many expressions where it decays to a pointer to its first element.

int numbers[3] = {10, 20, 30};

int* ptr = numbers;

std::cout << *ptr;

Output:

10

16. Accessing Array Elements Using a Pointer

int numbers[3] = {
    10, 20, 30
};

int* ptr = numbers;

std::cout << *ptr << std::endl;
std::cout << *(ptr + 1) << std::endl;
std::cout << *(ptr + 2);

Output:

10
20
30

Pointer arithmetic can be used to move between elements of an array.

17. Pointer Arithmetic

When a pointer points to an array element, adding 1 moves it to the next element of that type.

int numbers[3] = {
    10, 20, 30
};

int* ptr = numbers;

std::cout << *ptr << std::endl;

ptr++;

std::cout << *ptr;

Output:

10
20

18. Incrementing and Decrementing Pointers

int numbers[3] = {
    10, 20, 30
};

int* ptr = numbers;

ptr++;

std::cout << *ptr << std::endl;

ptr--;

std::cout << *ptr;

For pointers into the same array, ++ moves to the next element and -- moves to the previous element.

19. Pointers and Functions

A pointer can be passed to a function when the function needs to work with the original object.

void changeValue(int* ptr) {

    *ptr = 100;
}

int main() {

    int number = 10;

    changeValue(&number);

    std::cout << number;

    return 0;
}

Output:

100

20. Pointer and Pass by Address

Passing a pointer allows a function to access the object through its address.

void increase(int* number) {

    (*number)++;
}

int main() {

    int value = 10;

    increase(&value);

    std::cout << value;

    return 0;
}

Output:

11

21. const with Pointers

A pointer can be used with const to control whether the pointed-to value can be changed through that pointer.

int number = 10;

const int* ptr = &number;

Through ptr, the value cannot be modified.

// *ptr = 20;  // Not allowed

The original variable itself may still be modified through another valid means.

22. Pointer to const vs const Pointer

These two declarations have different meanings.

const int* ptr1;

Here, the pointer can be changed to point somewhere else, but the pointed-to value cannot be modified through ptr1.

int* const ptr2 = &number;

Here, the pointer itself cannot be changed to point somewhere else, but the pointed-to integer can be modified through ptr2.

23. Dynamic Memory with new

The new operator can dynamically allocate memory and return its address.

int* ptr = new int;

*ptr = 50;

std::cout << *ptr;

delete ptr;

Memory obtained with new should be released with delete when it is no longer needed.

24. Dynamic Array with new[]

A dynamic array can be created using new[].

int* numbers = new int[5];

numbers[0] = 10;
numbers[1] = 20;
numbers[2] = 30;
numbers[3] = 40;
numbers[4] = 50;

delete[] numbers;

Memory allocated using new[] should be released using delete[].

25. Smart Pointers

Modern C++ provides smart pointers that help manage dynamically allocated objects automatically.

#include <memory>

std::unique_ptr<int> ptr =
    std::make_unique<int>(50);

std::cout << *ptr;

A std::unique_ptr automatically releases the object when the smart pointer goes out of scope.

26. Common Pointer Mistakes

  • Dereferencing a null pointer.
  • Using an uninitialized pointer.
  • Accessing an object after it has been destroyed.
  • Using a pointer after its allocated memory has been released.
  • Forgetting delete for memory allocated with new.
  • Using delete instead of delete[] for memory allocated with new[].
  • Performing invalid pointer arithmetic.
Important: Pointer errors can cause undefined behavior. Use pointers carefully and prefer safer abstractions such as references, containers, and smart pointers when appropriate.

27. Practical Swap Program Using Pointers

#include <iostream>

void swapValues(int* a, int* b) {

    int temp = *a;

    *a = *b;

    *b = temp;
}

int main() {

    int x = 10;
    int y = 20;

    std::cout << "Before swap: "
              << x << " "
              << y << std::endl;

    swapValues(&x, &y);

    std::cout << "After swap: "
              << x << " "
              << y;

    return 0;
}

Output:

Before swap: 10 20
After swap: 20 10

28. Practical Array Traversal Using a Pointer

#include <iostream>

int main() {

    int numbers[5] = {
        10, 20, 30, 40, 50
    };

    int* ptr = numbers;

    for (int i = 0; i < 5; i++) {

        std::cout << *(ptr + i)
                  << " ";
    }

    return 0;
}

Output:

10 20 30 40 50

29. Best Practices for Pointers

  • Initialize pointers before using them.
  • Use nullptr for a pointer that points to nothing.
  • Check nullable pointers before dereferencing them.
  • Understand who owns dynamically allocated memory.
  • Match new with delete and new[] with delete[].
  • Prefer smart pointers for owning dynamically allocated objects.
  • Avoid unnecessary raw pointer ownership.
  • Use references when an address-based interface is not required.

30. Pointers – Final Summary

Concept Meaning
Pointer A variable that stores the address of an object.
& Operator Gets the address of an object in an appropriate expression.
* Operator Dereferences a pointer to access the pointed-to object.
nullptr Represents a null pointer value.
Pointer Arithmetic Allows movement between elements of the same array.
new Dynamically allocates an object.
delete Releases an object allocated with new.
new[] Dynamically allocates an array.
delete[] Releases an array allocated with new[].
Smart Pointer Helps manage dynamic object lifetime automatically.
int number = 10;

int* ptr = &number;

std::cout << *ptr;

📌 Key Points

  • A pointer stores the memory address of another object.
  • The & operator can obtain an object's address.
  • The * operator can dereference a pointer.
  • Changing *ptr can change the original object.
  • Pointer types should be compatible with the objects they point to.
  • nullptr represents a null pointer.
  • Pointers can be used with arrays and functions.
  • Pointer arithmetic is commonly used with elements of the same array.
  • new and delete manage dynamically allocated objects.
  • Modern C++ provides smart pointers for safer ownership management.

🧠 Quick Quiz

Question: What does a pointer normally store?