Expensive post-increment operation

Объект постпостепенно увеличивается, когда предварительное постепенное увеличение быстрее

Описание

Этот дефект повышен, когда вы используете постинкрементную или постдекрементную операцию вместо более эффективной преинкрементной или преддекрементной операции. Преинкрементная операция одинаково или более эффективна, когда все эти условия верны:

  • Пред и шаг сообщения или декрементные операции заданы для объекта.

  • Тип возврата постинкрементной или декрементной операции является дорогим, чтобы скопировать.

  • Возвращенное значение не использовано.

  • Тип возврата преинкрементной или декрементной операции не является дорогим, чтобы скопировать, такие как ссылка.

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

Риск

Постинкрементные или декрементные операции создают копию объекта, постепенно увеличивают или постепенно уменьшают оригинал, и затем возвращают скопированный объект. Когда объект является дорогим, чтобы скопировать, и вы не используете возвращенную копию объекта, постинкрементная или постдекрементная операция неэффективна. Используйте преинкрементную или преддекрементную операцию, которая не копирует объект и обычно возвращает ссылку на постепенно увеличенный или декрементный объект. Непреднамеренно использующий постинкремент вместо преинкремента с большим объектом может сделать код неэффективным. Код, который использует неэффективные постинкрементные или постдекрементные компиляции операций и ведет себя правильно. Неэффективные операции могут остаться необнаруженными.

Исправление

Когда вы не будете использовать возвращенный объект от декрементной или инкрементной операции, используйте преинкрементную операцию.

При итерации по каждому элементу контейнера вы можете хотеть использовать циклы, которые не требуют инкрементных или декрементных операций, таких как std::for_each или основанный на области значений for цикл. Эти циклы оптимизированы для таких итераций. Они не требуют ручных инкрементных или декрементных операций.

Повышения производительности могут варьироваться на основе компилятора, реализации библиотеки и среды, которую вы используете.

Примеры

развернуть все

// Using C++ 03
#include <complex>
#include <iterator> // istream_iterator
#include <sstream> // istringstream
#include <string>
#include <vector>

std::vector< std::complex< double > > deserialize( const std::string& s )
{
	std::vector< std::complex< double > > v;
	std::stringstream iss( s );
	for( std::istream_iterator< std::complex< double > > it( iss );
	     it != std::istream_iterator< std::complex< double > >(); it++ ) //Noncompliant
	{ v.push_back( *it ); }
	return v;
}

В этом примере постинкрементные операции выполняются на дорогих итераторах. Polyspace® принимает, что версией C++ является C++ 03. Используйте опцию анализа -cpp-version при помощи значения cpp03.

В функциональном deserialize, for циклы выполняют итерации по std::istream_iterator< std::complex< double > > итератор it. Поскольку эти итераторы являются дорогими, чтобы скопировать, постинкрементная операция является более дорогой, чем преинкрементная операция. Дорогой постинкремент является ненужным и неэффективным, потому что постепенно увеличенный итератор не используется. Polyspace отмечает постинкрементные операции.

Коррекция

Можно зафиксировать эти дефекты несколькими способами. Например, замените постинкрементные операции преинкрементными операциями. Если C++ 11 доступен, вы можете хотеть использовать основанные на области значений циклы for, когда вы выполняете итерации по каждому элементу контейнера.

#include <complex>
#include <iterator> // istream_iterator
#include <sstream> // istringstream
#include <string>
#include <vector>

std::vector< std::complex< double > > deserialize( const std::string& s )
{
	std::vector< std::complex< double > > v;
	std::stringstream iss( s );
	for( std::istream_iterator< std::complex< double > > it( iss );
	     it != std::istream_iterator< std::complex< double > >(); ++it ) //Compliant
	{ v.push_back( *it ); }
	return v;
}

Информация о результате

Группа: Производительность
Язык: C++
Значение по умолчанию: Off
Синтаксис командной строки: EXPENSIVE_POST_INCREMENT
Удар: низко
Введенный в R2021b