﻿# Storage duration

Storage duration is the identifier's property that defines the rules according to which an object is created and destroyed\. There are 4 types of storage duration: _automatic_, _static_, _thread local_ and _dynamic_\.

Storage duration is closely related to the lifetime of an object\. For example, two global objects with the _static storage duration_ property have the same lifetime – the entire program execution time\. At the same time, two objects with _dynamic storage duration_ will have different lifetimes\. Their lifetimes depend on when the corresponding [dynamic memory management](https://en.cppreference.com/w/cpp/memory) functions are called\.

## Automatic storage duration

Objects that have _automatic storage duration_ are created upon entry into the code block that encloses the objects\. These objects are destroyed upon exit from the code block\. Such objects are local objects declared without the _static_,_ extern_, or _thread\_local_ specifiers\.

Here's a synthetic code example:

```cpp
#include <vector>
#include <string>

class Forecaster { .... };

float Convert(const std::string &temp);

std::vector<float>
PredictTemperatureForInterval(int first_day,
                              int last_day,
                              const Forecaster &forecaster)
{
  auto forecast = forecaster.Predict(GetTodayDate());
  if (first_day == last_day)
  {
    std::string single_temperature = forecast.GetTemperature(first_day);
    if (!Validate(single_temperature))
    {
      return {};
    }

    return { Convert(single_temperature) };
  }
  else
  {
    std::vector<float> multiple_temperatures;
    for (auto curr_day = first_day; cur_day < last_day; ++cur_day)
    {
      std::string curr_temperature = forecast.GetTemperature(curr_day);
      if (!Validate(curr_temperature)
      {
        return {};
      }
      multiple_temperatures.push_back(Convert(cur_temperature));
    }

    return multiple_temperatures;
  }
}
```

In the example, the _forecast_, _single\_temperature_, _multiple\_temperatures_ and _cur\_day_ have _automatic storage duration\._ However, the lifetime for each of the variables varies\.

The lifetime of the _forecast_ variable ends when execution reaches the end of the _PredictTemperatureForInterval_ function body\. The lifetime of _single\_temperature_ is _than_–branch of the _if_ statement\. The lifetime of _multiple\_temperatures_ — _else_–branch of the _if_ statement; and the lifetime of _cur\_day_ — a body of the _for_ loop\.

## Static storage duration

For objects that have _static storage duration_, storage is allocated when the program starts execution and deallocated when the program ends execution\. In this case, the object itself is created before the first access to this object\. Objects that have _static storage duration_ are all identifiers declared at some namespace scope, plus those identifiers declared with _static_ or _extern_ specifier\. For each identifier that has _static storage duration_, only one instance of the object is created\.

Let's look at the example:

```cpp
class Logger { .... };

static Logger Logger;

int Calc(int arg);

int CalcWithLogging (int arg)
{
  static int counter = 0;
  ++counter;
  Logger.Log(counter);
  return Calc(arg);
}
```

In this code fragment, the _logger_ and _counter_ variables have _static storage duration_\. For both variables, the storage is allocated when the program starts execution\. The _logger_ variable is a global variable\. Its initialization is the call of the _Logger_ class default constructor\. The initialization occurs before the _main_ function starts executing\. The _counter_ variable is a local variable of the _CalcWithLogging_ function\. The variable initialization occurs during the first call of the function\. If the _CalcWithLogging_ function is not called during the execution of the program, the initialization of _counter_ variable doesn't occur\. At the same time, the storage for _counter_ is allocated and deallocated accordingly\.

## Thread local storage duration

For objects that have _thread storage duration_, storage is allocated when the thread is initialized and deallocated when the thread ends\. The object itself is created before the first access to this object\. Each thread has its own instance of the object\. For the identifier to have _thread storage duration_, it must be declared with the _thread\_local_ specifier\. The declaration of an object that have _threadstorage duration_ may also contain the _static_ or _extern_ specifiers\. In this case, these specifiers do not affect the _storage duration_ but determine its [_linkage_](https://pvs-studio.com/en/blog/terms/6506/)\.

Here's a synthetic code example:

```cpp
#include <string>
#include <string_view>
#include <iostream>
#include <syncstream>
#include <thread>

thread_local std::string str;

void AppendSuffix(std::string_view suffix)
{
  str += suffix;
}

void ThreadFunc(const std::string &value)
{
  AppendSuffix(value);
  std::osyncstream { std::cout } << str;
}

int main()
{
  AppendSuffix("main");
  std::thread t1 { ThreadFunc, "thread 1 " };
  std::thread t2 { ThreadFunc, "thread 2 " };
  t1.join();
  t2.join();
  std::cout << str;
}
```

In this example, the _str_ variable has _thread storage duration_\. When executing the program, a copy of the _str_ variable is created for each of the _t1_ and _t2 _streams_\._ The program will show one of two outputs: "thread 1 thread 2 main", "thread 2 thread 1 main" — it depends on the execution order of the threads\.

## Dynamic storage duration

To create or destroy an object that has _dynamic storage duration_, you need to use special functions for [dynamic memory management](https://en.cppreference.com/w/cpp/memory)\. To create such an object, for example, you can use the [_new_](https://en.cppreference.com/w/cpp/memory/new/operator_new) operator\. In this case, this object will exist until the corresponding [_delete_](https://en.cppreference.com/w/cpp/memory/new/operator_delete) operator is called\. Let's look at the following code example:

```cpp
void Foo()
{
  int *pInt = new int;
  *pInt = 12;
  cout << *pInt << '\n';
  delete pInt;
}
```

Here, the _pInt_ variable has _dynamic storage duration_\. The storage for the variable is allocated during the _new_ operator execution and is deallocated when executing the _delete_ operator\.