A pointer is a variable that stores the memory address of another variable. This capability allows pointers to manipulate data in memory.
Instead of directly containing a data value, a pointer contains the address where that value is located. Therefore, they are one of the simplest ways to perform a reference.
Pointers are a feature inherited from C. They are very much hated and loved (both unjustifiably)
One of C++‘s goals is to reduce or eliminate the use of pointers. However, they are still necessary.
Definition of a pointer
The basic syntax for defining a pointer is:
type *pointerName;
Where:
type
is the data type the pointer points to.pointerName
is the name of the pointer.
For example,
int *ptr;
In this example, ptr
is a pointer to an integer.
Dereference operator
The dereference operator *
is used to access the value of the variable that the pointer points to.
int var = 10;
int *ptr = &var;
std::cout << "Value of var: " << var << std::endl;
std::cout << "Value of var using pointer: " << *ptr << std::endl;
Assignment of addresses
To assign a memory address to a pointer, the address operator &
is used.
int var = 10;
int *ptr = &var;
Here, ptr
stores the address of var
.
Pointers and arrays
Arrays and pointers are closely related in C++. The name of an array is itself a pointer to the first element of the array.
int arr[5] = {1, 2, 3, 4, 5};
int *ptr = arr;
std::cout << "First element of the array: " << *ptr << std::endl;
std::cout << "Second element of the array: " << *(ptr + 1) << std::endl;
In this example, ptr
points to the first element of the array arr
.
Pointers and functions
Pointers can be used to pass large data structures to functions without the need to copy them, which is efficient in terms of memory and time.
#include <iostream>
void increment(int *ptr) {
(*ptr)++;
}
int main() {
int num = 10;
increment(&num);
std::cout << "Value of num after incrementing: " << num << std::endl;
return 0;
}
In this example, the function increment
directly modifies the value of num
through a pointer.
Pointers and dynamic memory
In C++, memory can be managed dynamically using the new
and delete
operators.
Dynamic memory allocation
int *ptr = new int;
*ptr = 20;
std::cout << "Value stored in dynamic memory: " << *ptr << std::endl;
delete ptr;
In this example, memory for an integer is dynamically allocated and then freed.
Dynamic arrays
int *arr = new int[5];
for (int i = 0; i < 5; ++i) {
arr[i] = i * 2;
}
for (int i = 0; i < 5; ++i) {
std::cout << "arr[" << i << "] = " << arr[i] << std::endl;
}
delete[] arr;
Here, memory is allocated and freed for a dynamic array.
Pointers to pointers
A pointer to a pointer is a variable that contains the address of a pointer, allowing additional levels of indirection.
int var = 5;
int *ptr = &var;
int **pptr = &ptr;
std::cout << "Value of var: " << var << std::endl;
std::cout << "Value of var using ptr: " << *ptr << std::endl;
std::cout << "Value of var using pptr: " << **pptr << std::endl;
Best practices
Initialize pointers
Always initialize pointers.
int *ptr = nullptr;
Using uninitialized pointers can cause undefined behavior.
Free memory
Make sure to free any dynamically allocated memory.
int *ptr = new int;
delete ptr;
Not freeing dynamically allocated memory can result in memory leaks.
Use nullptr
Use nullptr
instead of NULL
or 0
for null pointers.
int *ptr = nullptr;
Complete example
Let’s look at a somewhat broader example, where we would see dynamic management of a list of integers.
#include <iostream>
class IntegerList {
private:
int *data;
int capacity;
int size;
public:
IntegerList(int cap) : capacity(cap), size(0) {
data = new int[capacity];
}
~IntegerList() {
delete[] data;
}
void add(int value) {
if (size < capacity) {
data[size++] = value;
} else {
std::cerr << "List capacity exceeded" << std::endl;
}
}
void display() const {
for (int i = 0; i < size; ++i) {
std::cout << data[i] << " ";
}
std::cout << std::endl;
}
};
int main() {
IntegerList list(10);
list.add(1);
list.add(2);
list.add(3);
std::cout << "Elements in the list: ";
list.display();
return 0;
}
In this example, a class IntegerList
is created that manages a list of integers dynamically, demonstrating the creation, use, and freeing of dynamic memory.
It does not mean that this is the best way to solve the problem. It is an example to illustrate the use of pointers.