主要内容

Unnecessary copy caused by type conversion

Mismatched type between const reference and its initializer results in unnecessary copy

Since R2026a

Description

This defect occurs when the type of the initializer of a const reference is not an exact match but is compatible with the type of the reference. For example, consider this code

std::map<std::string, std::string> myMap;

for(const std::pair<std::string, std::string> &element : myMap) {
//...
}
The type of the const reference element is std::pair<std::string, std::string>. This reference is initialized by elements of the std::map object myMap, which has the type std::pair<const std::string, std::string>. The type of element is not an exact match with the type of the elements of myMap. An object with the exact required type is constructed by copy from the initializer. Polyspace® reports a defect.

Risk

When the type of a const reference is compatible with but is not an exact match of the type of the initializer, the compiler makes a copy of the initializer that has the exact same type as the reference. The reference points to this copy. For example, in the preceding code, element points to copies of the elements of myMap instead of pointing to the elements themselves. Copying the initializer in such cases is unexpected and can be expensive.

Fix

To fix this defect, avoid type mismatch when declaring a reference. Use the auto keyword whenever possible. This way, the compiler deduces the correct required type. For example:

std::map<std::string, std::string> myMap;

for(auto &element : myMap) {
//...
}

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

Examples

expand all

In this example, the range-based for loop iterates over the elements of the map employees. The code attempts to extract the elements by reference using employee. The type of empolyee is std::pair<std::string, std::string>. The type of elements of the map is std::pair<const std::string, std::string>. which is not an exact match of the type for employee. Because the types are compatible, the elements of employees are copied into temporary objects of type std::pair<std::string, std::string> and employee refers to these temporary copies. The copying of the elements is unnecessary and expensive. Polyspace reports a defect.

#include <map>
#include <string>
#include <tuple>

bool has_any_missing_data(const std::map<std::string, std::string> &employees) {
    for(const std::pair<std::string, std::string> &employee : employees) {
        if(employee.second.empty()) {
            return true;
        }
    }
    return false;
}

Correction — Use auto

To fix this defect, use auto as the type for employee.

#include <map>
#include <string>
#include <tuple>

bool has_any_missing_data(const std::map<std::string, std::string> &employees) {
    for(auto &employee : employees) {
        if(employee.second.empty()) {
            return true;
        }
    }
    return false;
}

Result Information

Group: Performance
Language: C++
Default: Off
Command-Line Syntax: EXPENSIVE_COPY_FROM_TYPE_CONVERSION
Impact: Medium
PQL Name: std.defects.EXPENSIVE_COPY_FROM_TYPE_CONVERSION

Version History

Introduced in R2026a