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 create a reference.
Pointers are a feature inherited from C. They are both hated and loved (both unjustly)
One of the goals of C++ is to reduce or eliminate the use of pointers. However, they are still necessary.
Definition of a pointer
The basic syntax to define a pointer is:
type *pointerName;
Where:
type
is the data type to which the pointer points.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 to which the pointer points.
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 the need to copy them, which is efficient in terms of memory and time.
Example of Functions with Pointers
#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 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
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 of nullptr
Use nullptr
instead of NULL
or 0
for null pointers.
int *ptr = nullptr;
Complete Example: Dynamic Management of an Integer List
#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 release of dynamic memory.