Анализатор обнаружил контейнер из стандартной библиотеки C++, который можно заменить на другой контейнер в целях оптимизации.
Для определения, какой именно контейнер лучше подойдет в конкретном случае, применяется эвристика, основанная на типах операций, которые производят с контейнером. Кроме этого, анализатор вычисляет алгоритмическую сложность всех операций и предлагает контейнер, у которого она будет ниже.
В сообщении указывается причина замены:
Пример:
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', можно избежать динамической аллокации памяти. Оптимизированный код:
void f()
{
std::array a{1, 2, 3};
}
Анализатор не предлагает такую замену, если суммарный размер элементов превышает 16 килобайт, а также если вектор приходит в функцию снаружи, возвращается из функции, или передается в другую функцию параметром.
В следующем фрагменте кода сообщение не выдается несмотря на то, что размер контейнера известен:
std::vector<int> f()
{
std::vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
return v;
}
Следующий пример, который можно оптимизировать:
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'. Можно произвести замену. Оптимизированный код:
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();
}
}
Следующий пример, который можно оптимизировать:
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' не отличаются с точки зрения алгоритмической сложности. Однако, в случае с вектором элементы в памяти будут расположены последовательно. Это может увеличить производительность, так как последовательный доступ к памяти позволяет эффективно использовать кэш процессора. Оптимизированный код:
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 << ' ';
}
}