Main Content

Expensive post-increment operation

Object is post-incremented when pre-incrementing is faster

Since R2021b

Description

This defect is raised when you use the post-increment or post-decrement operation instead of a more efficient pre-increment or pre-decrement operation. The pre-increment operation is equally or more efficient when all of these conditions are true:

  • Pre and post increment or decrement operations are defined for the object.

  • The return type of post-increment or decrement operation is expensive to copy.

  • The returned value is unused.

  • The return type of pre-increment or decrement operation is not expensive to copy, such as a reference.

The efficiencies of pre-increment and pre-decrement operations depends on the version and implementation of the C++ standard that you use. If you switch C++ version or the library implementation, you might see a change in the number of violation of this check.

Risk

Post-increment or decrement operations create a copy of the object, increment or decrement the original, and then return the copied object. When the object is expensive to copy and you do not use the returned copy of the object, the post-increment or post-decrement operation is inefficient. Use a pre-increment or pre-decrement operation, which does not copy the object and typically returns a reference to the incremented or decrement object. Inadvertently using post-increment instead of pre-increment with a large object might make the code inefficient. Code that uses inefficient post-increment or post-decrement operations compiles and behaves correctly. The inefficient operations might remain undetected.

Fix

When you do not use the returned object from a decrement or increment operation, use a pre-increment operation.

When iterating over each element of a container, you might want to use loops that do not require increment or decrement operations, such as std::for_each or the range-based for loop. These loops are optimized for such iterations. They do not require manual increment or decrement operations.

Performance improvements might vary based on the compiler, library implementation, and environment that you are using.

Examples

expand all

// 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++ ) 
	{ v.push_back( *it ); }
	return v;
}

In this example, post-increment operations are performed on expensive iterators. Polyspace® assumes that the C++ version is C++03. Use the analysis option -cpp-version by using the value cpp03.

In the function deserialize, the for loops iterate over a std::istream_iterator< std::complex< double > > iterator it. Because these iterators are expensive to copy, the post-increment operation is more expensive than the pre-increment operation. The expensive post-increment is unnecessary and inefficient because the incremented iterator is not used. Polyspace flags the post-increment operations.

Correction

You can fix these defects in several ways. For instance, replace the post-increment operations by pre-increment operations. If C++11 is available, you might want to use range-based for loops when you iterate over each element of a container.

#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 ) 
	{ v.push_back( *it ); }
	return v;
}

Result Information

Group: Performance
Language: C++
Default: Off
Command-Line Syntax: EXPENSIVE_POST_INCREMENT
Impact: Low

Version History

Introduced in R2021b