﻿# V826\. Consider replacing standard container with a different one\.

Анализатор обнаружил контейнер из стандартной библиотеки C\+\+, который можно заменить на другой контейнер в целях оптимизации\.

Для определения, какой именно контейнер лучше подойдет в конкретном случае, применяется эвристика, основанная на типах операций, которые производят с контейнером\. Кроме этого, анализатор вычисляет алгоритмическую сложность всех операций и предлагает контейнер, у которого она будет ниже\.

В сообщении указывается причина замены:

* "The size is known at compile time" – размер контейнера известен во время компиляции, возможна замена на статический массив \(std::array\)\.
* "Elements are added, read and erased only from front/back" – контейнер реализует LIFO\-очередь, можно использовать 'std::stack'\.
* "Elements are added to front/back, read and erased from the opposite side" – контейнер реализует FIFO\-очередь, можно использовать 'std::queue'\.
* "Insertion and removal of elements occur at either side of the container" – элементы добавляются или удаляются с головы и с хвоста\. В этом случае эффективно использовать 'std::deque' или 'std::list'\.
* "Insertions occur at the front side, and the container is traversed forward" – элементы добавляются только с головы и происходит обход в направлении хвоста\. Контейнер используется, как 'std::forward\_list'\.
* "Insertions occur at the back side, and the container is traversed" – элементы добавляются в хвост, происходит обход в любом направлении\. Для такого использования подходит 'std::vector'\.
* "Contiguous placement of elements in memory can be more efficient" – если использовать 'std::vector', то алгоритмическая сложность операций не изменится, но последовательное расположение элементов в памяти может улучшить производительность\.
* "Overall efficiency of operations will increase" – контейнер выбран на основании статистического анализа\.

Пример:

```cpp
void f()
{
  std::vector<int> v;
  v.push_back(1);
  v.push_back(2);
  v.push_back(3);

  for (auto value : v)
  {
    std::cout << value << ' ';
  }
}
```

Анализатор выдает следующее сообщение:

V826\. Consider replacing the 'v' std::vector with std::array\. The size is known at compile time\.

Здесь размер вектора известен во время компиляции\. Если использовать вместо него 'std::array', можно избежать динамической аллокации памяти\. Оптимизированный код:

```cpp
void f()
{
  std::array a{1, 2, 3};
}
```

Анализатор не предлагает такую замену, если суммарный размер элементов превышает 16 килобайт, а также если вектор приходит в функцию снаружи, возвращается из функции, или передается в другую функцию параметром\.

В следующем фрагменте кода сообщение не выдается несмотря на то, что размер контейнера известен:

```cpp
std::vector<int> f()
{
  std::vector<int> v;
  v.push_back(1);
  v.push_back(2);
  v.push_back(3);

  return v;
}
```

Следующий пример, который можно оптимизировать:

```cpp
void f(int n)
{
  std::vector<int> v;

  for (int i = 0; i < n; ++i)
  {
    v.push_back(i);
  }

  for (int i = 0; i < n; ++i)
  {
    std::cout << v.back() << ' ';
    v.pop_back();
  }
}
```

Анализатор выдает следующее сообщение:

V826\. Consider replacing the 'v' std::vector with std::stack\. Elements are added, read and erased only from front/back\.

Здесь элементы добавляются в хвост вектора, а затем происходит их последовательное чтение и удаление\. Вектор используется, как 'std::stack'\. Можно произвести замену\. Оптимизированный код:

```cpp
void f(int n)
{
  std::stack<int> v;

  for (int i = 0; i < n; ++i)
  {
    v.push(i);
  }

  for (int i = 0; i < n; ++i)
  {
    std::cout << v.top() << ' ';
    v.pop();
  }
}
```

Следующий пример, который можно оптимизировать:

```cpp
void f(int n)
{
  std::deque<int> d;
  for (int i = 0; i < n; i++)
  {
    d.push_back(i);
  }

  for (auto value : d)
  {
    std::cout << value << ' ';
  }
}
```

Анализатор выдает следующее сообщение:

V826\. Consider replacing the 'd' std::deque with std::vector\. Contiguous placement of elements in memory can be more efficient\.

В этом случае 'std::deque' и 'std::vector' не отличаются с точки зрения алгоритмической сложности\. Однако, в случае с вектором элементы в памяти будут расположены последовательно\. Это может увеличить производительность, так как последовательный доступ к памяти позволяет эффективно использовать кэш процессора\. Оптимизированный код:

```cpp
void f(int n)
{
  std::vector<int> d;
  for (int i = 0; i < n; i++)
  {
    d.push_back(i);
  }

  for (auto value : d)
  {
    std::cout << value << ' ';
  }
}
```