Мы используем куки, чтобы пользоваться сайтом было удобно.
Хорошо
to the top
>
>
>
V823. Decreased performance. Object may…
menu mobile close menu
Проверка проектов
Сообщения PVS-Studio
Диагностики общего назначения (General Analysis, C++)
Диагностики общего назначения (General Analysis, C#)
Диагностики общего назначения (General Analysis, Java)
Микрооптимизации (C++)
Диагностика 64-битных ошибок (Viva64, C++)
Реализовано по запросам пользователей (C++)
Cтандарт MISRA
Стандарт AUTOSAR
Стандарт OWASP (C++)
Стандарт OWASP (C#)
Проблемы при работе анализатора кода
Дополнительная информация
toggle menu Оглавление

V823. Decreased performance. Object may be created in-place in a container. Consider replacing methods: 'insert' -> 'emplace', 'push_*' -> 'emplace_*'.

05 Фев 2020

Анализатор обнаружил потенциальное использование менее эффективного метода. При вставке временного объекта в контейнер при использовании методов 'insert' / 'push_*' он конструируется снаружи контейнера и затем перемещен/скопирован внутрь контейнера.

Методы 'emplace' / 'emplace_*' в свою очередь позволяют устранить один избыточный вызов конструктора перемещения / копирования и создают объект "по месту" внутри контейнера, идеально передавая параметры функции конструктору объекта.

Анализатор предлагает следующие замены:

  • insert -> emplace
  • insert_after -> emplace_after
  • push_back -> emplace_back
  • push_front -> emplace_front

Пример кода:

std::string str { "Hello, World" };
std::vector<std::string> vec;
std::forward_list<std::string> forward_list;
std::list<std::string> list;
std::map<std::string, std::string> map;

....

vec.push_back(std::string { 3, 'A' });
forward_list.push_front(std::string { str.begin(), str.begin() + 6 });
list.push_front(str.substr(7));
list.push_back(std::string { "Hello, World" });
map.insert(std::pair<std::string, std::string> { "Hello", "World" });

Оптимизированный код:

std::vector<std::string> vec;
std::forward_list<std::string> forward_list;
std::list<std::string> list;
std::map<std::string, std::string> map;

....

vector.emplace_back(3, 'A');
forward_list.emplace_front(string.begin(), string.begin() + 6);
list.emplace_front(str.begin() + 7, str.end());
list.emplace_back("Hello, World");
map.emplace("Hello", "World");

В некоторых случаях такая замена может привести к потере базовой гарантии безопасности исключений. Рассмотрим пример:

std::vector<std::unique_ptr<int>> vectUniqP;
vectUniqP.push_back(std::unique_ptr<int>(new int(0)));
auto *p = new int(1);
vectUniqP.push_back(std::unique_ptr<int>(p));

В таком случае замена 'push_back' на 'emplace_back' может привести к утечке памяти, если 'emplace_back' бросит исключение в связи с отсутствием памяти. Анализатор не выдает срабатывания на подобные случаи и не предлагает замену. Если же код был изменен на ошибочный, анализатор выдаст предупреждение V1023.

Иногда замена вызовов методов 'insert' / 'push_*' на их аналог 'emplace' / 'emplace_*' не принесет оптимизации:

std::string foo()
{
  std::string res;
  // doing some heavy stuff
  return res;
}

std::vector<std::string> vec;
....
vec.push_back(foo());

В этом примере метод 'emplace_back' будет иметь такую же эффективность, что и вставка элемента через 'push_back'. Однако, предупреждение всё равно выдаётся для единообразия. Во всех подобных ситуациях рационально сделать замену, чтобы код смотрелся единообразно и при его просмотре не приходилось каждый раз задумываться, стоит использовать 'emplace*' или нет. Если пользователь не согласен с таким подходом, он может рассматривать подобные предупреждения как ложные и подавлять их.

Примечание. К описанной здесь рекомендации стоит подходить разумно, а не формально. Например, замена

widgets.push_back(Widget(foo, bar, baz));
// на
widgets.emplace_back(Widget(foo, bar, baz));

не даёт никакого выигрыша в скорости работы программы. Более того, использование 'emplace_back' может замедлить скорость компиляции кода. Подробнее эта тема освящена в статье "Don't blindly prefer emplace_back to push_back". Наша команда выражает Arthur O'Dwyer благодарность за эту публикацию.

close form

Заполните форму в два простых шага ниже:

Ваши контактные данные:

Шаг 1
Поздравляем! У вас есть промокод!

Тип желаемой лицензии:

Шаг 2
Team license
Enterprise license
** Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности
close form
Запросите информацию о ценах
Новая лицензия
Продление лицензии
--Выберите валюту--
USD
EUR
RUB
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

close form
Бесплатная лицензия PVS‑Studio для специалистов Microsoft MVP
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

close form
Для получения лицензии для вашего открытого
проекта заполните, пожалуйста, эту форму
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

close form
Мне интересно попробовать плагин на:
* Нажимая на кнопку, вы даете согласие на обработку
своих персональных данных. См. Политику конфиденциальности

close form
check circle
Ваше сообщение отправлено.

Мы ответим вам на


Если вы так и не получили ответ, пожалуйста, проверьте, отфильтровано ли письмо в одну из следующих стандартных папок:

  • Промоакции
  • Оповещения
  • Спам