Last Updated:

Pointers in C++

When running any program, all the data necessary for its work must be loaded into the computer's RAM. To access variables in memory, special addresses are used that are written in hexadecimal form, for example, or .0x1000x200

If too many variables in memory are required that the hardware itself cannot accommodate, the system will become overloaded or hang.

If we declare variables statically, as we did in the previous lessons, they remain in memory until the program finishes its work, and then they are destroyed.

This approach may be acceptable in simple examples and simple programs that do not require a lot of resources. If our project is a huge software package with high functionality, declaring variables in this way, of course, would be quite unwise.

Can you imagine if the notorious Battlefield 3 used this method of working with data? In this case, the most avid gamers would have to reboot their high-load systems with the reset button after a few seconds of the game.

The fact is that playing the same Battlefield, the gamer at each new time sees various objects on the monitor screen, for example, now I shoot at the enemy, and after a fraction of a second he already falls dead, creating around himself a lot of special effects, such as dust, shadows, etc.

Naturally, all this takes up some space in the computer's RAM. If you do not destroy unused objects, very soon they will fill the entire amount of PC resources.

For these reasons, most languages, including C/C++, have the concept of a pointer. A pointer is a variable that stores the address of a ram cell, such as a 0x100.

We can access, for example, an array of data through a pointer that will contain the address of the beginning of the range of memory cells storing this array.

After this array is no longer needed to execute the rest of the program, we will simply free up memory at the address of this pointer, and it will again become available to other variables.

The following is a concrete example of accessing variables through a pointer and directly.

Example of using static variables

#include <iostream>
using namespace std;

int main()
{
     int a; // Declaring a static variable
     int b = 5; // Initialization of the static variable b

     a = 10;
     b = a + b;
     cout << "b is " << b << endl;
     return 0;
}

Example of using dynamic variables

#include <iostream>
using namespace std;

int main()
{
     int *a = new int; // Declaring a pointer for a variable of type int
     int *b = new int(5); // Pointer initialization

     *a = 10;
     *b = *a + *b;

     cout << "b is " << *b << endl;

     delete b;
     delete a;

     return 0;
}

The syntax of the first example should already be familiar to you. We declare/initialize static variables a and b, and then perform various operations directly on them.

In the second example, we operate dynamic variables by means of pointers. Let's look at the general syntax of pointers in C++.

Memory allocation is performed using the new operator and has the form: data_type *pointer_name = new data_type;, for example, int *a = new int;. After successfully performing such an operation, the range of cells necessary to store a variable of type int is allocated in the computer's RAM.

It is logical to assume that different amounts of memory are allocated for different types of data. You should be especially careful when working with memory, because it is the program errors caused by a memory leak that are among the most difficult to find. It can take an hour, a day, a week to debug a program in search of one insignificant error, depending on the perseverance of the developer and the amount of code.

Initialization of a value located at the pointer address is performed in a similar way, only at the end are placed parentheses with the desired value: data type *pointer_name = new data_type(value). In our example, this is int *b = new int(5)..

In order to get the address in memory referenced by the pointer, the name of the pointer variable with the prefix &. before it (not to be confused with the link mark in C++).

For example, to display the address of the memory location referenced by pointer b in the second example, we write . In my system, I got the value 0x1aba030. You may have it different because the addresses in RAM are allocated in such a way as to minimize fragmentation as much as possible. Since, in any system, the list of running processes, as well as the amount and bit depth of memory may differ, the system itself distributes the data to ensure minimal fragmentation.cout << "Address of b is " << &b << endl;

In order to get a value that is located at the address referenced by the pointer, the prefix *is used. This operation is called pointer dereferencing.

In the second example, we display a value that is in a memory cell (I have this 0x1aba030): . In this case, the * sign must be used.cout << "b is " << *b << endl;

To change the value at the address referenced by the pointer, you must also use an asterisk, for example, as in the second example, .*b = *a + *b;

  • When we operate with data, we use the *
  • When we operate with addresses, we use the sign &

In these things, very often there are misunderstandings, and by the way, not only among beginners. Many of those who started programming with the same php also often experience similar confusion when working with memory.

To free the memory allocated by the new operator, use the delete statement.

Example of memory freeing

#include <iostream>
using namespace std;

int main()
{
     // Memory allocation
     int *a = new int;
     int *b = new int;
     float *c = new float;

     // ... Any actions of the program

     // Free allocated memory
     delete c;
     delete b;
     delete a;

     return 0;
}

When using an operator for a pointer, the * sign is not used.delete