C++. Classes of memory that can be declared when working with classes and class objects. Keywords register, extern, static, mutable

C++. Classes of memory that can be declared when working with classes and class objects. Keywords register, extern, static, mutable


Contents


1. What memory classes can class objects and classes be declared with?

Class objects and classes can be declared with these memory classes:

  • automatic (auto);
  • registered (register);
  • external (extern);
  • static.
  • mutable.

For each storage class is determined by its own specifier: auto, register, extern, static. The specifiers of memory classes determine how the variable should be stored.

 

2. How is the ‘auto’ memory class used for classes? Example

The ‘auto‘ memory class defines automatic variables. By default, these are local variables that are placed on the stack or internal registers of the processor. The “lifetime” of an automatic variable is limited by the execution time of a function (method) or a block in which this variable is defined. When you normally declare a local class object or a local variable, for example

int a;
double x;
char c;
CMyClass MC; // class object

this variable gets the ‘auto‘ memory class.

It is important that after the declaration, the automatic variables are initialized. Since, the contents of the cells that are allocated for these variables is undefined.

Example. Let’s have a fragment of the function that computes the sum of the elements of the array A consisting of n integers.

int MySum(int A[], int n)
{
    // declaring the automatic variable sum
    int sum; // the beginning of the "life" or the existence of the variable sum
    sum = 0;

    for (int i=0; i<n; i++) // a loop that contains a block {...}
    {
        // the beginning of the existence of the automatic variable i
        sum = sum + A[i]; //
        // the end of the existence of the automatic variable i
    }

    return sum;
    // the end of the existence of the automatic variable sum
}

The MySum() function has the following automatic variables:

  • A, n – formal parameters are also automatic variables;
  • sum, i – internal local variables of the MySum() function.

This also applies to declaring a class object. If a class object is declared in the method (function), then this object has an auto memory class.

For example. Suppose, is given a certain class CMyClass.

class CMyClass
{
    int d;

    public:
    // constructor
    CMyClass(void) { d = 0; };

    // class methods
    int Get(void) { return d; }
    void Set(int nd) { d = nd; }
};

Then, in some function MyFun() the object of the class will belong to the memory class ‘auto‘.

void MyFun(...)
{
    CMyClass MC; // declaration of a class object with the memory class 'auto'
    ...
}

 

3. How is ‘register‘ memory class used? Example

A class object can be declared with the ‘register‘ keyword. Setting the ‘register‘ keyword – this is an indication to the compiler allocate the internal registers of the processor to store the object data. But this does not mean that the compiler will necessarily place the object data in the registers of the processor. In addition, when ‘register‘ keyword is specified, the compiler can place the data in the cache. The main purpose of declaring a variable (object) with the ‘register‘ keyword is to provide the fastest possible access to this variable and handling this variable.

Example. Let’s have the declaration of class CMyClass.

class CMyClass
{
    int d;

    public:
    // constructor
    CMyClass(void);

    // class methods
    int Get(void) { return d; }
    void Set(int nd) { d = nd; }
};

// constructor
CMyClass::CMyClass(void)
{
    d = 0;
}

A class object is a variable of the type of this class. Therefore, an object like a variable can have a ‘register‘ memory class.

// declaration of a class object with 'register' memory class
register CMyClass MC1;

int t;
t = MC1.Get(); // t = 0

MC1.Set(15);
t = MC1.Get(); // t = 15

 

4. How is the ‘extern‘ memory class used?

If a class is declared in one module, but you want to declare that this class is external in another module, then this class is declared with the ‘extern‘ keyword. In this case, you do not need to further describe the internal implementation of data and class methods.

For example. Let two modules “MyClass.h” and “Main.h” be given. The “MyClass.h” module implements the declaration of the CMyClass class. The module “Main.h” implements the use of the class “MyClass.h”, which is connected from the outside with the #include directive.

To use the capabilities of the external CMyClass class, the following code must be added in the text of the module “Main.h”

#include "MyClass.h"
extern class CMyClass; // declaration that the CMyClass class is external

In this case, the class CMyClass is considered external, that is, one that has a memory class ‘extern‘.

 

5. How are static class objects used?

A class object can be used with the ‘static‘ keyword. In this case, the place for the object is allocated in a fixed memory area. Working with static class objects that are declared with the ‘static‘ keyword is no different from working with regular static variables.

More information about using static variables in classes is described in the article:

Example. Let the class CMyCounter be given.

class CMyCounter
{
    public:
    int d;
    CMyCounter(void) { d = 0; }; // class constructor
    ~CMyCounter(void) {}; // class destructor
};

The class declares a public variable d, a constructor, and a destructor. The class constructor sets the initial value of d to zero.

To demonstrate the use of a static class object, you need to write a function that changes the values of d relative to its previous value. In this case, a function is implemented that increases the previous value of d by 1. The function declares a static object of class CMyCounter.

// function in which a static object of class is declared
int IncMyCounter(void)
{
    // declaring a class object with a static memory class
    static CMyCounter MC; // the object is placed in a fixed memory area
    MC.d = MC.d + 1; // increasing to 1
    return MC.d;
}

Using the IncMyCounter() function from another program code demonstrates the fact that a static object is not destroyed after the function call is terminated

...

int t;
t = IncMyCounter(); // t = 1
t = IncMyCounter(); // t = 2 - taken into account the previous value CMyCounter::d
t = IncMyCounter(); // t = 3 - taken into account the previous value CMyCounter::d

...

As you can see from the above code snippet, the function is called 3 times. The last two calls take into account the previous value of the variable d of the CMyCounter class.

If you declare an MC object of the CMyCounter class in the IncMyCounter() function without the ‘static‘ keyword

void IncMyCounter(void)
{
    // declaring a class object without the 'static' keyword
    CMyCounter MC; // temporary (non-fixed) memory
    MC.d = MC.d + 1; // increase by 1
}

then this object will refer to the auto memory class. In this case, each time the IncMyCounter() function is called,

...

int t;
t = IncMyCounter(); // t = 1
t = IncMyCounter(); // t = 1 - the previous value of CMyCounter :: d is not taken into account
t = IncMyCounter(); // t = 1 - the previous value of CMyCounter :: d is not taken into account

...

for the internal variable d of the CMyCounter object, the memory will be allocated again. As a result, the variable d of the MC object will be:

  • created anew in the non-fixed area of memory when it is declared;
  • initialized using the class constructor (d = 0);
  • destroyed when you exit the IncMyCounter() function, because the MC class object is declared as automatic (auto memory class).

 

6. In which cases is the memory class ‘mutable‘ used for the class object? Example

The mutable memory class is used in conjunction with so-called constant functions (functions that are declared with the ‘const‘ keyword).

Example of a function with a const modifier in the CMyRadius class

class CMyRadius
{
    double r; // object radius

    public:
    // constant function - calculates the area of a circle
    double GetSquare(void) const
    {
        return (double)(3.1415 * r * r);
    }
}

If a constant function is declared in a class, then this function can not modify class data. This is the main purpose of declaring a constant function in a class – not to allow modification of the object that will cause it. That is, the following function in the CMyRadius class can not be implemented:

// constant function - sets new r - disabled
void SetR(double nr) const
{
    r = nr;
}

But, there are times when you need to change data values using a constant function. For example, if the class data can also include a complex object of another class, in which some of the data needs to be changed.

To get out of this situation, you need to use the mutable keyword when declaring class data. In our example, so that you can change the value of the variable r using a constant function, you need to declare it as follows

mutable double r; // object radius

Such a record means that the value of r in the class can be changed using a constant function. That is, the constant function Set() can be declared in the class.

After the changes, the class text is as follows:

class CMyRadius
{
    mutable double r; // r is declared as mutable

    public:
    // constant function - calculates the area of the circle - it is possible
    double GetSquare(void) const
    {
        return (double)(3.1415 * r * r);
    }

    // constant function - sets a new r - it is possible
    void SetR(double nr) const
    {
        r = nr;
    }
}

Using a class in another program code

CMyRadiusMR;

int t;
MR.Set(2);
t = MR.GetSquare(); // t = 12.566

The above statements are only valid for native classes. In the CLR environment in managed classes, the use of const and volatile qualifiers is not supported

 


Related topics