範囲ベースの for ループの反復における計算量の多いコピー
範囲ベースの for ループのループ変数が参照されるのではなく範囲要素からコピーされるため、非効率なコードになる
説明
この欠陥は、範囲ベースの for ループのループ変数が、範囲要素を参照で読み取るのではなく、範囲要素からコピーされた場合に発生します。範囲要素は必要な場合にのみコピーします。これは、範囲要素をコピーすると非効率なコードになる可能性があるためです。この欠陥は、ループ変数が変更されておらず、以下の条件のいずれかが true の場合に発生します。
コピーするループ変数が大きなトリビアル コピー可能な型変数である。オブジェクトが大きい場合は、トリビアル コピー可能なオブジェクトのコピーの方が参照より計算量が多くなります。
コピーされるループ変数が非トリビアル コピー可能な型である。このようなオブジェクトをコピーするには、参照よりも計算量の多い外部関数呼び出しが必要になります。オブジェクトが非トリビアル コピー可能かどうかをチェックするには、関数
std::is_trivially_copyableを使用します。この関数の詳細については、C++ リファレンスのstd::is_trivially_copyableを参照してください。
リスク
範囲ベースの for ループは、ループの反復ごとに時間のかかるループ変数のコピーが実行された場合に非効率になる可能性があります。次のコードについて考えます。
void foo( std::map<std::string, std::string> const& property_map )
{
for( std::pair< const std::string, std::string > const property: property_map)
{}
}ループ変数 property は、const& ではなく const として宣言されています。for ループの反復ごとに、std::pair オブジェクトがマップ property_maps からループ変数 property にコピーされます。propert の宣言から & が欠落しているため、反復ごとに、参照操作ではなく、計算量の多いコピー操作が行われるため、非効率なコードになります。このコードはコンパイル可能で、正しく機能するため、非効率な for ループが検出されない可能性があります。同様の非効率性の原因については、計算量の多い値渡しと計算量の多い値返しを参照してください。
修正方法
この欠陥を修正するには、範囲ベースの for ループのループ変数を const& として宣言します。次のコードについて考えます。
void foo( std::map<std::string, std::string> const& property_map )
{
for( std::pair< const std::string, std::string > const& property: property_map)
{}
}property は const& として宣言されているため、この変数は、リソースをコピーせずに、ループ反復ごとにマップ property_map の異なる要素を参照します。各反復での計算量の多いコピーを回避することによって、コードが効率化します。パフォーマンスの改善の程度は、使用しているコンパイラ、ライブラリ実装、環境によって異なる可能性があります。
例
結果情報
| グループ: パフォーマンス |
| 言語: C++ |
| 既定値: オフ |
コマンド ライン構文: EXPENSIVE_RANGE_BASED_FOR_LOOP_ITERATION |
| 影響度: Medium |
バージョン履歴
R2020b で導入