このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。
範囲ベースの 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 で導入