Pointers in C++

Pointers in C++

Pointers in C++ are variables that store the address of other variables. They help in direct memory accessing and also support dynamic memory allocation. Pointers are widely used in various real-life applications such as game development. In this article, we will discuss what a pointer is, creating, declaring, and initializing a pointer, dereferencing a pointer, types of pointers, uses, smart pointers, and best practices using pointers in C++.

Table of Contents:

What Are Pointers in C++?

What Are Pointers in C++

Pointers are the variables that are used to store the memory address of other variables. A pointer does not store the direct value of a variable, it holds the location in memory where a value is stored. They can be used with any data types, either basic such as integer, char, etc, or user-defined data types such as classes or structures.

Creating a Pointer in C++

A pointer can be created by declaring it with a data type and initializing it with the address of a variable.

Syntax:

type* pointerName = &variableName;
  • type – It is the data type of the variable to which the pointer will point.
  • *pointerName – It is the pointer variable name with theence operator, which declares the pointer.
  • &variableName – It is the address-of operator, which will store the memory address of the variable.

Declaring and Initializing a Pointer in C++

A pointer in C++ is declared by defining the data type of the variable it points to, with an asterisk *, and the pointer name. It is initialized by assigning it the address of a variable by using the & (addressof-operator).

Declaration Syntax:

dataType* pointerName;

Initialization Syntax:

pointerName = &variableName;

Example:

Cpp

Output:

Declaring and Initializing a Pointer in C++

The code shows how to declare and initialize a pointer in C++, which stores the address of the variable age in ptr, and then *ptr is used to access the value of age through the pointer.

Assigning an Address to a Pointer in C++

An address can be assigned to a pointer by using the address-of operator (&) on a variable.

Syntax:

int x = 10;
int* p; // declare pointer
p = &x; // assign address of x to pointer p

Example:

Cpp

Output:

Assigning an Address to a Pointer in C++

The code shows how the address of the variable number is assigned to the pointer ptr, and then *ptr is used to access its value, and ptr is used to print the address of the variable.

Dereferencing a Pointer in C++

Dereferencing a pointer is the process by which the value stored at the memory address of the variable the pointer is pointing to is accessed by using the * operator in C++.

Syntax:
int* ptr = &x;
int value = *ptr; // dereferencing to get the value of x

Example:

Cpp

Output:

Dereferencing a Pointer in C++

The code shows how to access the value of the variable at the memory address by using *. Here, *ptr is giving the value of the variable that is pointed to by ptr.

Modifying Address in C++ (Pointer Reassignment)

A pointer can be reassigned to store the address of another variable of the same type. Pointer reassignment allows the pointer to point to different data during the execution of a C++ program.

Example:

Cpp

Output:

Modifying Address in C++

The code shows how the pointer reassignment allows the ptr to point to a, and then ptr is updated to point to b, so that *ptr will give the value of b as an output.

Size of Pointers in C++

The size of a pointer in C++ depends on the CPU architecture and operating system of the computer, and not on the data type of the variable it points to. So, the size of a pointer in a system is the same for all pointers.

  • On a 32-bit system, all pointers are of 4 bytes.
  • On a 64-bit system, all pointers are of 8 bytes.

Example:

Cpp

Output:

Size of Pointers in C++

The code shows how the size of the pointer is determined by the system architecture, since the size of int, double, and char is 8 bytes, as the system is of 64-bit.

Special Types of Pointers in C++

Special Types of Pointers in C++

In C++, there are 5 special types of pointers that have a particular purpose. 

1. NULL Pointer

A NULL pointer is a pointer that does not point to any memory location, and is used to show that the pointer is intentionally not assigned to any variable.

Syntax:

Below are the modern and traditional ones.

int* ptr = nullptr;  // C++11 and later
int* ptr = NULL;     // Traditional C-style

Example:

Cpp

Output:

NULL Pointer

The code shows how the NULL pointer nullptr points to nothing, and then the output is printed as Pointer is NULL.

2. Void Pointer 

A void pointer in C++ is a pointer that can store the address of any data type, but it cannot be dereferenced directly without typecasting.

Syntax:

void* ptr;

Example:

Cpp

Output:

Void Pointer 

The code shows how a void* pointer is used to store the address of an int x, and then typecasts it to int* before dereferencing to access the value, and then the value is printed as an output.

3. Wild Pointer 

A wild pointer is a pointer that has been declared but not initialized, which points to a random memory location, which is leading to undefined behavior is accessed.

Syntax:

int* ptr;  // Wild pointer - contains garbage address

Example:

Cpp

Output:

Wild Pointer 

The code shows how a segmentation fault occurs because ptr is a wild pointer, it is uninitialized and points to an invalid memory location when it is dereferenced. 

4. Dangling Pointer

A dangling pointer occurs when a pointer continues to reference the memory that has already been freed or gone out of scope, and accessing such memory leads to undefined behavior.

Example:

Cpp

Output:

Dangling Pointer

The code shows how the address of a variable x, which goes out of scope after the function ends, is returned, making a ptr a dangling pointer and causing undefined behavior when dereferenced.

5. Constant Pointers

In C++, a constant pointer is declared in two main ways, with some restrictions.

a) Pointer to Constant (const int* ptr)

  • You can change the address that the pointer stores.
  • You cannot modify the value the pointer points to.

Example:

int x = 10, y = 20;
const int* ptr = &x; // can't change *ptr
ptr = &y; // allowed
//*ptr = 30; // error!

b) Constant Pointer (int* const ptr)

  • You cannot change the address that the pointer stores.
  • You can modify the value that the pointer points to.

Example:

int x = 10;
int* const ptr = &x; // can't change address
*ptr = 30; // allowed
//ptr = &y; // error!

c) Constant Pointer to Constant (const int* const ptr)

  • You cannot change the address or the value.

Example:

int x = 10;
const int* const ptr = &x;
//*ptr = 20; // error!
//ptr = &y; // error!

Pointers and Arrays in C++

The name of an array behaves like a pointer to its first element in C++, which allows you to use the pointers to access and manipulate the array elements.

Example:

Cpp

Output:

Pointers and Arrays in C++

The code shows how the array name acts as a pointer to its first element, so the elements can be accessed using pointer arithmetic *(arr + i) instead of arr[i].

Here is a difference table between Pointer and Array:

Aspect Pointer Array
Definition A variable that holds an address Collection of elements of the same type
Memory Allocation Dynamic (using new/malloc) Static (fixed at compile time)
Can it be reassigned? Yes, a pointer can point elsewhere No, the array name is fixed
Arithmetic Supports pointer arithmetic Array name allows arithmetic, but itself is not modifiable
Size with sizeof Gives the size of the pointer Gives the total size of an array in bytes

Pointer Arithmetic in C++

Pointer arithmetic in C++ allows to perform operations like addition or subtraction on pointers to navigate through memory, which is especially useful when working with arrays.

Valid Pointer Operations:

  • Incrementing and Decrementing: ++ or — helps to move the pointer to the next or previous element.
  • Addition of Integer: ptr + n helps to move the pointer forward by n elements.
  • Subtraction of Integer: ptr – n helps to move the pointer backward by n elements.
  • Subtraction of Two Pointers of the Same Type: It gives the number of elements between two pointers of the same type.
  • Comparison of Pointers and NULL:  It is used to check if a pointer is uninitialized or it is null (ptr == nullptr).

Example:

Cpp

Output:

Pointer Arithmetic in C++

The code shows how the pointer arithmetic works using a simple integer array for increment, decrement, add, subtract, pointer difference, and null comparison.

Get 100% Hike!

Master Most in Demand Skills Now!

Pointer to Pointer (Double Pointer) in C++

Pointer to Pointer (Double Pointer) in C++

A pointer to pointer is a variable that stores the address of another pointer. It allows indirect access to the value pointed to by a pointer. It is also called as double pointer.

Syntax:

int x = 10;
int* ptr = &x; // pointer to int
int** dptr = &ptr; // pointer to pointer to int

Example:

Cpp

Output:

Pointer to Pointer

The code shows how the pointer stores the address of another pointer and is used to access data indirectly using **dptr gives the value, and then printed to the console.

Pointer to Functions in C++

A pointer to a function allows to store the address of a function in a variable and calls the function using that pointer. It is commonly used in callbacks, event handling, and function dispatching.

Syntax:

returnType (*pointerName)(parameterTypes);

Example:

Cpp

Output:

Pointer to Functions in C++

The code shows how the function pointer stores the address of a function and calls the address indirectly using the pointer funcPtr().

Smart Pointers in C++

Smart Pointers in C++

Smart pointers are pointers in C++ that are used to manage dynamically allocated memory automatically. It makes sure that there is proper deallocation and also no memory leaks. They are part of the <memory> header in C++.

There are three types of smart pointers. They are:

  1. std::unique_ptr: It is a type of smart pointer that owns and manages a resource exclusively, and cannot be shared or copied.
  2. std::shared_ptr: It allows multiple pointers to share ownership of a dynamically allocated object.
  3. std::weak_ptr: It is a non-owning reference to an object managed by shared_ptr, and also used to avoid circular references.

Example:

Cpp

Output:

Smart Pointers in C++

The code shows how the unique_ptr, shared_ptr, and weak_ptr show exclusive ownership, shared ownership, and non-owning reference with the ptr, and then printed to the console.

Pointer vs Reference in C++

Pointers are used to store and manipulate memory addresses explicitly and can also be reassigned or set to null, while references are aliases to variables, safer and simpler, but cannot be reassigned or null.

Here is a difference table for pointer vs reference in C++:

Feature Pointer Reference
Syntax int* ptr = &x; int& ref = x;
Nullability Can be nullptr Cannot be null
Reassignment Can point to another variable Cannot be changed after binding
Indirection Requires * for access Used like the original variable
Memory Address Stores address explicitly Acts as an alias
Use in Arrays Commonly used with arrays Less flexible with arrays

Pointer and String Literals in C++

String literals in C++ are stored as constant character arrays, and a pointer can be used to refer to them. 

Example:

Cpp

Output:

Pointer and String Literals in C++

The code shows how a pointer can reference a string literal and access individual characters from the string “Hello, World” using pointer arithmetic, and then print it to the console.

Common Mistakes with Pointers in C++

  1. If you are using a pointer without initializing then it will lead to undefined behavior.
  2. If you are trying to access memory through a null or already freed pointer, then it can crash your program.
  3. When you forget to delete dynamically allocated memory can cause memory leaks.
  4. When the same memory is deleted twice then it can corrupt memory and crash the program.
  5. If there is any error in the calculations, then the pointer will point to invalid memory locations.
  6. Improper casting may lead to incorrect values and segmentation values.
  7. Trying to write to a string literal results in undefined behavior.
  8. Misusing dereferencing and address-of operators can lead to logic errors.

Best Practices for Using Pointers in C++

  1. You should initialize pointers to a valid address to avoid wild pointers.
  2. You must use the smart pointers to manage the dynamic memory efficiently.
  3. Always check the modern containers, such as vector or string, to avoid using new and delete manually.
  4. You must check for nullptr before dereferencing to prevent invalid memory access.
  5. You should use array indexing and iterators for better readability and minimizing pointer arithmetic.
  6. You must limit the pointer scope so that it can be used for the given time only.
  7. Always use const with pointers wherever it is possible to avoid the automatic modification of the data.

Debugging Pointers in C++

Below are a few methods that will help you to debug the pointers in C++:

1. Use Compiler Warnings and Flags

  • Compile your program with flags such as -Wall -Wextra -pedantic to find potential pointer misuse.
  • Enable sanitizers in your compiler by using this code.
g++ -fsanitize=address -g your_code.cpp

2. Check Initialization

  • You should always initialize pointers to nullptr and check before dereferencing.

3. Use Debuggers 

  • Use debuggers such as GDB, set breakpoints, inspect memory addresses, and pointer values using the code in bash.
gdb ./a.out
(gdb) break main
(gdb) run
(gdb) print ptr
(gdb) print *ptr

4. Use Valgrind

  • You must use Valgrind to detect memory leaks, invalid accesses, and misuses of pointers. 
valgrind ./a.out

Applications of Pointers in C++

  • Pointers are used for memory management, system calls, and accessing hardware through memory-mapped input output in operating systems.
  • They are also used in embedded systems for direct memory management and pointer arithmetic.
  • Pointers are used in game development to optimize real-time performance.
  • Pointers are used to create data structures for dynamic connectivity and storage.
  • They are also used in networking for buffers and callback functions for asynchronous communication.
  • Pointers are also used in compilers and interpreters for the symbol tables, syntax trees, and heap-based structures.
  • They are used in GUI toolkits such as event systems.
  • Pointers are used in scientific computations for large dynamic arrays and matrix structures for speed and memory efficiency.

Pointers vs Iterators in C++

Aspect Pointers Iterators
Definition Variables holding memory addresses. Objects for traversing containers.
Syntax int* ptr = &var; auto it = container.begin();
Type Safety Less type-safe, manual casting. Type-safe, container-specific.
Memory Management Manual (new/delete). Handled automatically by the container.
Use Case Low-level memory access. Traversing and manipulating STL containers.
Access Direct memory access. Abstracted access via container interface.
Arithmetic Pointer arithmetic allowed (ptr++). Iterator arithmetic via the container’s API (it++).
Container Support Arrays and dynamically allocated memory. Works with STL containers.
Safety Risk of invalid access (null, out-of-bounds). Safer, bounds-checked.
Performance Very efficient. Slightly less efficient due to abstraction.
Flexibility Very flexible, but can easily give errors. Safer but less flexible.
Ease of Use Requires more care. Easier to use, less error-prone.

Conclusion

Pointers are a powerful feature in C++ that helps in direct memory access and efficient data handling. There are various real-life applications of pointers, such as game development and data structures. There are also some disadvantages and mistakes that can occur due to the incorrect usage of pointers. So, by understanding pointers, their uses, common mistakes, debugging techniques, and best practices, you can easily write C++ programs using pointers efficiently.

FAQs on Pointers in C++

Q1. What is a pointer?

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

Q2. What is nullptr?

A null pointer is a pointer that does not point to any valid address.

Q3. What is the difference between a Pointer and a Reference?

The difference between a pointer and a reference is that a pointer can be reassigned and set to null, but a reference cannot be.

Q4. What is a dangling pointer?

A dangling pointer is a pointer referencing memory that has been deallocated or is out of scope.

Q5. Why should I use smart pointers?

You should use smart pointers to manage memory automatically and to avoid memory leaks and dangling pointers.

About the Author

Technical Research Analyst - Full Stack Development

Kislay is a Technical Research Analyst and Full Stack Developer with expertise in crafting Mobile applications from inception to deployment. Proficient in Android development, IOS development, HTML, CSS, JavaScript, React, Angular, MySQL, and MongoDB, he’s committed to enhancing user experiences through intuitive websites and advanced mobile applications.

Full Stack Developer Course Banner