Concept of Pointers and Memory in C++ Programming

This blog has discussed critical c++ concepts related to dangling pointers, bad pointers, memory leak, static memory, dynamic memory, reference variable, const and volatile keywords, template, etc.

Dangling pointers in C++

A pointer is a special kind of variable designed to store the memory address of another variable. Declaring a pointer is as simple as declaring any other variable, but it is tricky to handle. The dangling pointer is a similar tricky situation!

A pointer pointing to a memory location that has been deleted/de-allocated or falls out of scope is called Dangling Pointer. Here are some questions to ponder upon!

  • What is the impact of having dangling pointers in our program?
  • How can we avoid dangling pointers in our program?

Here are three scenarios when dangling pointers get created during coding:

A pointer to the memory that you have deleted

int main()
    int num = 47;
    int *ptr = #
    //ptr is pointing to a de-allocated memory
    //dangling pointer
    cout<< ptr << endl;

Returning local variable in a function call

int *fun()
    int num = 47;
    return &num;

int main()
    int *ptr = fun();
    //ptr falls out of scope
    //dangling pointer
    cout<< ptr << endl;

Pointing to a variable that is out of scope

int main()
    int *ptr;
        int num = 47;
        ptr = &num;
    // ptr goes out of scope
    // dangling pointer
    cout<< ptr << endl;

Memory leak in C++

A memory leak occurs when memory resources are allocated and not properly released once no longer required, often introduced through bad coding practices. If a program has memory leaks, its memory usage increases, and since all systems have limited memory, it can create problems. Here are some questions for you to ponder upon!

  • What are the impacts of memory leaks in our program?
  • How can we avoid memory leaks?

Memory leak scenario 1

void function()
    // memory allocated 
    int *ptr = new int [47];
    // returning without de-allocating memory

int main()
    return 0;

Memory leak scenario 2

void main()
    // memory allocated 
    int *ptr = new int [47];
    //reference to the memory removed 
    // without deallocating the memory
    ptr = NULL;

Bad pointer in C++

When a pointer is first allocated, it does not have a pointee i.e. pointer is "uninitialized" or "bad". A dereference operation on a bad pointer is a serious runtime error. The code will compile fine, but at run-time, each dereferences with a bad pointer will corrupt memory somehow. As a result, the program will crash sooner or later. The programmer's responsibility is to ensure that each pointer is assigned a pointee before it is used.

bad pointer code example in c++

Dereferencing the pointer value after it has been freed

ย Suppose we allocate a pointer and free the associated memory after using it. If we try to use the pointer again, it'll end in undefined behavior: maybe a crash will occur that depends on the system/platform's state. So, the idea would be never to use a pointer after it has been freed. Even a good practice is to set the pointer to ๐—ก๐—จ๐—Ÿ๐—Ÿ after it has been freed such that an access violation catches any attempt to use it again.

code example dereferencing the pointer value after it has been freed

So, here are some critical questions to explore:

  1. Is there a way to reuse the pointer again? Think!
  2. How does the system handle static and dynamic memory allocation and de-allocation?

Static memory in C++

ย A stack is an area in a computer's memory that is responsible for storing ๐˜๐—ฒ๐—บ๐—ฝ๐—ผ๐—ฟ๐—ฎ๐—ฟ๐˜† ๐˜ƒ๐—ฎ๐—ฟ๐—ถ๐—ฎ๐—ฏ๐—น๐—ฒ๐˜€. During runtime, variables are declared, stored, and initialized in the stack. Since the stack is temporary memory storage, the variables' memory gets automatically erased once the computational task is complete.

static memory code example in c++

An attempt to free memory on the stack using the ๐—ณ๐—ฟ๐—ฒ๐—ฒ() function will throw an ๐—ฎ๐—ฐ๐—ฐ๐—ฒ๐˜€๐˜€ ๐˜ƒ๐—ถ๐—ผ๐—น๐—ฎ๐˜๐—ถ๐—ผ๐—ป. Memory management on the stack(non-pointer variables) is carried out by the system implicitly.

Here are some critical questions to explore:

  1. What is the scope of variables stored in Stack Memory?
  2. How does the stack allocate the memory used by temporary variables?

Dynamic memory allocation in C++

ย ๐—›๐—ฒ๐—ฎ๐—ฝ memory, also known as ๐—ฑ๐˜†๐—ป๐—ฎ๐—บ๐—ถ๐—ฐ memory, is an alternative to local stack memory. Local memory is quite automatic: it is allocated automatically on function calls and deallocated automatically when a function exits.

dynamic memory allocation code example in c++

Heap memory is different in every way. The programmer has to explicitly request the allocation of a memory ๐—ฏ๐—น๐—ผ๐—ฐ๐—ธ of a particular size, and the block continues to be allocated until the programmer explicitly requests that it be deallocated. ๐—›๐—ฒ๐—ฟ๐—ฒ ๐—ฎ๐—ฟ๐—ฒ ๐˜€๐—ผ๐—บ๐—ฒ ๐—ฐ๐—ฟ๐—ถ๐˜๐—ถ๐—ฐ๐—ฎ๐—น ๐—พ๐˜‚๐—ฒ๐˜€๐˜๐—ถ๐—ผ๐—ป๐˜€ ๐˜๐—ผ ๐—ฒ๐˜…๐—ฝ๐—น๐—ผ๐—ฟ๐—ฒ:

  1. How is allocating memory on a heap an advantage over-allocating memory on a stack?
  2. Is it a good practice to reuse the pointer after freeing the dynamically allocated memory?

Character array and character pointer

We can initialize a string in C++ in different ways, like a character array or character pointer. Each one of them has its pros and cons.

character array and character pointer code example in c++

Here are some critical questions to explore:

  1. Find the similarities and differences between them?
  2. How does the system allocate memory in each case?
  3. Which one of them should we prefer and why?

Reference variable in C++

A reference variable is an alias, that is, another name for an already existing variable/memory instance. Once a reference is initialized with a variable, either the variable name or the reference name may refer to the variable. The reference variable, once defined to refer to a variable, cannot be changed to point to other variables.

reference variable code example in c++

Is the "&" operator always necessary while passing through reference?

When passing by reference, the caller does not always need to use the "&" operator to compute a new pointer to the value of interest. Sometimes the caller already has a pointer to the value of interest, so no new pointer computation is required. The pointer to the value of interest can be passed through unchanged.

"&" operator always necessary while passing through reference

The const keyword in C++

ย In C++, const is used to make some values constant throughout the program, or in other words, variables declared with the const keyword become constants and cannot be altered by the program.

Pointers can be declared using the const keyword too. When we use const with pointers, we can do it in two ways, either we can apply const to what the pointer is pointing to, or we can make the pointer itself a constant.

the const keyword in c++ code example

The volatile keyword in C++

ย In the C/C++ programming language, a variable or object declared with the volatile keyword usually has special properties related to optimization on objects that can change in ways that the compiler cannot determine.

the volatile keyword code example in c++

The optimizations are performed by caching variables in registers. The volatile keyword is designed to prevent the compiler from applying any optimizations on the code that assume values of variables cannot change "on their own."

ย The volatile keyword is intended to be used in combination with variables that are accessed and modified in different threads. Basically, without volatile, either writing multithreaded programs becomes difficult, or the compiler wastes vast optimization opportunities.

Templates in C++

Templates allow us to write generic programs in C++. In simple terms, we can create a single function or a class to work with different data types using templates.

templates code example in c++

The idea of C++ templates is simple: we can make code dependent on parameters so that it can be used in different situations by instantiating the parameters as needed. In all programming languages, the most basic form of code that takes a parameter is a function.

Enjoy learning!

Share Your Insights

โ˜† 16-week live DSA course
โ˜† 16-week live ML course
โ˜† 10-week live DSA course

More from EnjoyAlgorithms

Self-paced Courses and Blogs

Coding Interview

Machine Learning

System Design

Our Newsletter

Subscribe to get well designed content on data structure and algorithms, machine learning, system design, object orientd programming and math.