Unicorn with delicious cookie
Мы используем куки, чтобы пользоваться сайтом было удобно.
Хорошо
to the top
menu mobile close menu
Проверка проектов
Дополнительная информация
toggle menu Оглавление

V838. Temporary object is constructed during lookup in ordered associative container. Consider using a container with heterogeneous lookup to avoid construction of temporary objects.

02 Авг 2023

Анализатор обнаружил вызов функции поиска в ассоциативном упорядоченном контейнере ('std::set', 'std::miltiset', 'std::map' или 'std::multimap') c аргументом, тип которого отличается от типа ключа контейнера. В результате такого вызова произойдет создание временного объекта типа ключа из переданного аргумента.

Если конвертация типов является дорогой операцией (например, 'const char *' в 'std::string'), это может отразиться на производительности программы.

Начиная с C++14, можно избежать создания временного объекта. Для это нужно, чтобы компаратор упорядоченного ассоциативного контейнера поддерживал гетерогенный поиск. Для этого должны быть выполнены следующие условия:

  • Компаратор умел сравнивать тип передаваемого аргумента с типом ключа.
  • В компараторе объявлен псевдоним 'is_transparent'.

Анализатор выдает предупреждение в случае, если в компараторе не объявлено имя 'is_transparent'.

Рассмотрим пример кода:

void foo(const char *str)
{
  static std::set<std::string> cont;

  auto it = cont.find(str); // <=
  if (it != cont.end())
  {
    // do smth
  }
}

В примере контейнер 'cont' по умолчанию объявлен с компаратором типа 'std::less<std::string>'. Этот компаратор не поддерживает гетерогенный поиск. Поэтому при каждом вызове функции 'find' происходит создание временного объекта 'std::string' из 'const char *'.

Чтобы избежать создания временного объекта типа 'std::string', нужно использовать контейнер с компаратором, поддерживающим гетерогенный поиск и умеющим сравнивать 'std::string' c 'const char *'. Например, можно использовать 'std::set' с компаратором 'std::less<>':

void foo(const char *str)
{
  static std::set<std::string, std::less<>> cont;

  auto it = cont.find(str);
  if (it != cont.end())
  {
    // do smth
  }
}

Теперь при вызове функции 'find' временный объект типа 'std::string' не создается, и аргумент типа 'const char *' напрямую сравнивается с ключами.