Lesson 20
Pointers
Covers pointer declaration, initialization, dereferencing, null pointers, pointer arithmetic, and pointer to pointer.
Lesson content
What are pointers in C++?
A pointer is a variable that stores the memory address of another variable instead of storing the actual value.
int number = 25;
int* ptr = &number;The pointer ptr stores the memory address where number is located.
Why do pointers exist?
- Access memory directly
- Share data efficiently between functions
- Allocate memory dynamically
- Build complex data structures
- Avoid unnecessary copying of large objects
Real-world use cases
- Dynamic memory allocation
- Linked lists
- Trees and graphs
- Game development
- Operating systems
- Device drivers
- Database engines
- Smart pointers and resource management (RAII)
Memory address
Every variable is stored at a unique location in memory. The address-of operator (&) returns the memory address of a variable.
int number = 100;
cout << &number;
// Output (varies each run): 0x61ff08Declaring a pointer
dataType* pointerName;
int* ptr;Initializing a pointer
Pointers should always be initialized before use.
int number = 50;
int* ptr = &number;- number stores the value
- &number gives its address
- ptr stores that address
Dereferencing a pointer
The dereference operator (*) accesses the value stored at the address held by the pointer.
cout << *ptr;
// Output: 50Null pointer
A pointer that does not point to any valid object should be initialized to nullptr, which helps avoid undefined behavior caused by uninitialized pointers.
int* ptr = nullptr;Pointer arithmetic
Pointers can be incremented or decremented to move through contiguous memory locations, such as elements of an array.
ptr++;
ptr--;Pointer to pointer
A pointer can store the address of another pointer.
int value = 10;
int* ptr = &value;
int** ptr2 = &ptr;Example 1: Declaring and using a pointer
#include <iostream>
using namespace std;
int main()
{
int number = 25;
int* ptr = &number;
cout << "Value = " << *ptr;
return 0;
}
// Output: Value = 25Example 2: Display value and address
#include <iostream>
using namespace std;
int main()
{
int number = 100;
int* ptr = &number;
cout << "Value: " << *ptr << '\n';
cout << "Address: " << ptr;
return 0;
}Example 3: Modify a variable using a pointer
#include <iostream>
using namespace std;
int main()
{
int marks = 75;
int* ptr = &marks;
*ptr = 90;
cout << marks;
return 0;
}
// Output: 90Example 4: Pointer arithmetic with an array
#include <iostream>
using namespace std;
int main()
{
int numbers[5] = {10, 20, 30, 40, 50};
int* ptr = numbers;
for (int i = 0; i < 5; i++)
{
cout << *(ptr + i) << " ";
}
return 0;
}
// Output: 10 20 30 40 50Example 5: Pointer to pointer
#include <iostream>
using namespace std;
int main()
{
int value = 50;
int* ptr = &value;
int** ptr2 = &ptr;
cout << **ptr2;
return 0;
}
// Output: 50Common mistakes and pitfalls
- Dereferencing an uninitialized pointer. Fix: initialize with nullptr or a valid address
- Dereferencing nullptr. Fix: check if the pointer is not nullptr first
- Forgetting to initialize a pointer. Fix: always initialize pointers
- Using a pointer after deleting memory. Fix: set the pointer to nullptr after deletion
- Confusing * and &. Fix: use & for addresses and * for dereferencing
// Wrong
int* ptr;
cout << *ptr;// Correct
int value = 10;
int* ptr = &value;
cout << *ptr;Best practices
- Always initialize pointers
- Use nullptr instead of NULL or 0
- Prefer smart pointers (unique_ptr, shared_ptr) over raw pointers for ownership
- Check for nullptr before dereferencing when appropriate
- Keep pointer usage as simple as possible
- Use references instead of pointers when nullability or reseating isn't required
When not to use this
- Simple variables or references are sufficient
- Automatic memory management is preferred
- Ownership semantics are needed (use smart pointers)
- Working with standard containers like std::vector instead of manual dynamic arrays
Summary
- Pointers store memory addresses instead of values
- The address-of operator (&) obtains a variable's address
- The dereference operator (*) accesses the value at an address
- Initialize pointers before using them
- Use nullptr for pointers that don't currently point to an object
- Pointer arithmetic allows navigation through contiguous memory
- Modern C++ often prefers smart pointers for resource management
Frequently asked questions
What is a pointer in C++?
A variable that stores the memory address of another variable.
What is the difference between * and &?
& returns the memory address of a variable, while * declares a pointer and dereferences it to access the pointed-to value.
What is a null pointer?
A pointer that doesn't point to any valid object, represented in modern C++ using nullptr.
Why are pointers important in C++?
They enable direct memory access, dynamic memory allocation, efficient parameter passing, and advanced data structures.
Should I always use raw pointers?
No. Prefer references when appropriate and smart pointers for owning resources; raw pointers suit non-owning access and low-level programming.