DEV Community

Jaya Prakash
Jaya Prakash

Posted on • Edited on

Pointers vs References: A Deep Dive into C++ Fundamentals

 C++ provides two primary mechanisms for indirectly accessing and modifying data:

  • Pointers, which store memory addresses
  • References, which act as aliases for existing variables

Though both can be used to access other variables, they serve different purposes, with distinct syntax, behavior, and safety characteristics.

What is a Pointer?

A pointer is a variable that holds the address of another variable.It enables indirect access and manipulation of data stored in a different memory location by referencing its address.

  • int* ptr: Declares a pointer to an int. It can store the address of an integer variable.
  • &x: The address-of operator (&) is used to get the memory address of a variable x.

Visualizing a pointer

Pointer Dereferencing

Dereferencing a pointer using (*) gives access to the actual variable it points to, allowing you to read or modify it directly.

Null Pointers

Pointers can point to nothing, a null value

Pointer Arithematic

int* ptr = arr;
This means ptr points to the first element of the array. In C++, the array name (arr) automatically acts like a pointer to its first element.

Accessing Elements Using Pointer Arithmetic

  • *ptr gives the value at the first element.
  • *(ptr + 1) moves the pointer one step ahead and accesses the second element.
  • You can keep doing *(ptr + i) to access arr[i].

Accessing Class Members via Pointer

ptr->x and ptr->show() access members through the pointer using the -> operator.

What is a Reference?

A reference is an alias for another variable. Once initialized, it cannot be changed to refer to another object.

  • Always initialized during declaration
  • No nullptr, no reassignment
  • Looks like a variable, behaves like an alias
  • References are used to avoid copying of data, making the function more efficient, especially with large objects.
  • They allow functions to modify the original variable directly.

  • Pass-by-reference is useful when:
    • You want to avoid performance overhead of copying.
    • You need the function to update the caller's variable.

Passing by Reference Without Modification

Using const std::string& means the function receives the original variable by reference, but promises not to modify it. This ensures safety while avoiding the overhead of copying.

When to Use Pointers

  • Dynamic memory allocation
  • Nullable objects
  • Data structures (linked lists, trees)
  • Interfacing with C libraries
  • Arrays and pointer arithmetic

When to Use References

  • Function arguments/return types
  • Operator overloading
  • Avoiding copies
  • Cleaner syntax for indirection

Advanced Topics

Working with Pointers and Custom Classes in C++

In C++, when you create objects using new, you get a pointer to that object. You must manually delete it to free memory.

new returns a pointer to the heap-allocated object.

You must call delete to avoid memory leaks.

Returning by Reference

Allows function to return modifiable values:

Never return a reference to a local variable causes dangling reference.

Example (Dangling Reference):

  • x is a local variable, so it gets destroyed when getRef() ends.
  • Returning a reference to it creates a dangling reference, leading to undefined behavior.

Pointers to Pointers

You can use a pointer to a pointer (int**) to dynamically create and manage 2D arrays.

Smart Pointers (Modern C++)

Smart pointers are class templates in C++ that manage the lifetime of dynamically allocated objects. Unlike raw pointers (int*), they automatically free memory when it's no longer needed, helping prevent:

  • Memory leaks
  • Dangling pointers
  • Manual delete calls

They're part of the C++ Standard Library (since C++11) and live in the <memory> header.

Types of Smart Pointers

std::unique_ptr

Owns a resource exclusively (no other pointer can point to it). Automatically deletes the object when it goes out of scope.

std::shared_ptr

Allows multiple pointers to share ownership of a dynamically allocated object. Internally uses reference counting.

std::weak_ptr

A non-owning smart pointer that observes a shared_ptr without affecting its reference count. Prevents cyclic references.

A weak_ptr does not own the object, so it can’t access it directly.To use the object safely, you use the .lock() method.

.lock() does two things:

  1. Checks if the object still exists (hasn't been deleted).
  2. Returns a shared_ptr to access the object only if it's still alive.

What is Reference Count in Smart Pointers?

Reference count is a number that keeps track of how many shared_ptrs are pointing to the same object.

This count:

  • Increases when a new shared_ptr is created from an existing one.
  • Decreases when a shared_ptr is destroyed or reset.

When the reference count drops to zero, it means no one is using the object anymore, so it gets automatically deleted — no manual delete() needed

Top comments (0)