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 an reference.
Pointers are a feature inherited from C. They are both hated and loved (both unjustifiably).
One of the goals of C++ is to reduce or eliminate the use of pointers. However, they are still necessary.
Defining a Pointer
The basic syntax to define a pointer is:
type *pointerName;
Where:
typeis the data type the pointer points to.pointerNameis 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 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;
Assigning Addresses
To assign a memory address to a pointer, the address-of 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 needing 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 increment function 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 allocated dynamically 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 for a dynamic array is allocated and freed.
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
Ensure to free any dynamically allocated memory.
int *ptr = new int;
delete ptr;
Not freeing dynamically allocated memory can result in memory leaks.
Use of nullptr
Use nullptr instead of NULL or 0 for null pointers.
int *ptr = nullptr;
Complete Example
Let’s look at a slightly broader example, showing 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 IntegerList class is created that manages a list of integers dynamically, demonstrating the creation, use, and release of dynamic memory.
This does not mean it is the best way to solve the problem. It is an example to illustrate the use of pointers.
