Copying an object is an expensive operation, especially if the type of the object is not trivial to copy. To avoid creating an unnecessary copy of such object, use const references.
The analyser has found a local variable that can't be automatically moved. The reason for this behavior is the constness of the variable. Consider declaring the variable without the qualifier const
.
std::vector
in loop CXX-P2007Manually appending a significant number of elements to a std::vector
without reserving the memory upfront can cause performance issues as the memory needs to be reallocated and copied every time the std::vector
's size increases. This can be costly if many items need to be pushed into the std::vector
. Consider using the std::vector::reserve()
function to preallocate memory for the std::vector
before a loop containing a std::vector::push_back
.
float
to double
in a math function CXX-P2001Calling math functions from the C libray that only accept double
with float
arguments causes an implicit type promotion of the float
argument. Type promoting float
to double
costs extra space in memory, it also costs extra instructions for the conversion from float
and lastly vectorisation of float
is a lot more efficient compared to double
.
std::string
CXX-P2003Found using sub-string based method find
for a character look-up.
A parameter is declared to be call-by-value when a const reference will suffice. This parameter type is expensive to copy.
The check is only applied to parameters of types that are expensive to copy which means they are not trivially copyable or have a non-trivial copy constructor or destructor.
std::move
on a trvially copyable parameter CXX-P2010std::move
converts an instance from lvalue to rvalue. The move or move-assignment constructor is invoked on such conversions if they exist. When the following arguments are used with std::move
, the std::move
has no effect.
The for-loop's range declaration variable is copied in every iteration when it's a non-reference type. Consider using a const reference for range declaration variable.
A move or move-assignment constructor without noexcept
or a noexcept
with an expression that evaluates to boolean false
.
To properly initialize class data members or base classes in a move constructor's initializer list, it's important to ensure that the object hierarchy is being move-initialized, rather than copy-initialized. An rvalue reference parameter is itself an lvalue and steps must be taken to preserve move semantics. See the examples below(1). The lvalue can be turned into an xvalue(same as glvalue & rvalue) by passing it to std::move
and it can be used to perform initialization.
Algorithms inside the associative containers have more efficient implementations than standard linear search, as they make use of efficient key-retrieval methods present to locate the elements.
So while the standard algorithm uses std::iterator
base and has a linear complexity of O(n)
even when used on the associative containers, most internal methods of associative containers would have sub-linear time complexity.
std::set::find
is more expressive and easier to read than std::find
when used with a set. It makes it clear that you are searching for an element in a set, rather than in some arbitrary range.