﻿# V1055\. The 'sizeof' expression returns the size of the container type, not the number of elements\. Consider using the 'size\(\)' function\.

Анализатор обнаружил в качестве аргумента оператора 'sizeof' переменную типа "STL\-подобный контейнер"\.

Рассмотрим следующий пример:

```cpp
#include <string>

void foo(const std::string &name)
{
  auto len = sizeof(name) / sizeof(name[0]);
  ....
}
```

Выражение 'sizeof\(name\)' возвращает не суммарный размер элементов в контейнере в байтах \(или просто количество элементов\), а именно размер типа контейнера, отведенный для имплементации\. Например, типичная имплементация 'std::string' может содержать 3 указателя \(стандартная библиотека libc\+\+, 64\-битная система\), т\.е\. 'sizeof\(name\) \=\= 24'\. Размер же реальной хранимой строки чаще всего отличается от этого значения\.

Ошибка подобного рода может появиться в проекте в результате рефакторинга старого кода:

```cpp
#define MAX_LEN(str) ( sizeof((str)) / sizeof((str)[0]) - 1 )
typedef char MyString[256];

void foo()
{
  MyString str { .... };
  ....
  size_t max_len = MAX_LEN(str);
}
```

При замене псевдонима 'MyString' с типа 'char\[256\]' на 'std::string' вычисление максимально допустимой длины строки станет некорректным\.

Для получения реального размера STL\-подобных контейнеров стоит использовать публичную функцию\-член '\.size\(\)':

```cpp
#include <string>
void foo(const std::string &name)
{
  auto len = name.size(); 
}
```

Если подразумевалось именно вычисление размера имплементации контейнера, то для лучшего понимания кода предпочтительнее передавать в качестве операнда оператора 'sizeof' тип контейнера, прямым способом или через оператор 'decltype' \(C\+\+11\) для переменных:

```cpp
#include <string>

void foo(const std::string &str)
{
  auto string_size_impl1 = sizeof(std::string);
  auto string_size_impl2 = sizeof(decltype(str));
}
```

Диагностика также знает о существовании контейнера 'std::array' и не выдает на нем срабатывание при его использовании в качестве операнда оператора 'sizeof':

```cpp
template <typename T, size_t N>
void foo(const std::array<T, N> &arr)
{
  auto size = sizeof(arr) / sizeof(arr[0]); // ok
}
```

Начиная со стандарта C\+\+17, рекомендуется использовать свободную функцию 'std::size\(\)', которая умеет работать как встроенными массивами, так и всеми типами контейнеров, имеющими публичную функцию\-член '\.size\(\)':

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

void foo()
{
  int arr[256] { .... };

  std::vector vec { .... };
  std::string str { .... };
  std::set    set { .... };
  std::list  list { .... };

  auto len1 = std::size(arr);
  auto len2 = std::size(vec);
  auto len3 = std::size(str);
  auto len4 = std::size(set);
  auto len5 = std::size(list);
}
```