このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。
計算量の多い値返し
関数が参照やポインターではなく値で大きな出力を返す
説明
この欠陥は、関数が、大きな出力オブジェクトを参照やポインターで返すのではなく、値で返す場合に発生します。
このチェッカーは、以下の条件の両方が true の場合に起動されます。
返されたオブジェクトのアドレスが
return
ステートメント後も有効なままである。返されたオブジェクトが以下のいずれかである。
非トリビアル コピー可能なオブジェクト。このようなオブジェクトを値で返すには、参照で返すよりも計算量の多い外部関数呼び出しが必要になります。オブジェクトが非トリビアル コピー可能かどうかをチェックするには、関数
std::is_trivially_copyable
を使用します。この関数の詳細については、C++ リファレンスのstd::is_trivially_copyable
を参照してください。大きなトリビアル コピー可能なオブジェクト。オブジェクトが大きい場合は、トリビアル コピー可能なオブジェクトを値で返すと計算量が多くなります。
この欠陥は、返されたオブジェクトが以下の場合は発生しません。
コピーの計算量が少ない。
一時オブジェクトまたは非静的ローカル オブジェクト。
リスク
オブジェクトを参照またはポインターで返すことができる場合は、大きなオブジェクトを値で返そうとすると非効率になります。関数は、&
または *
が欠落していることによって、大きなオブジェクトを誤って値で返す場合があります。このような非効率な return ステートメントは検出されない可能性があります。次のコードについて考えます。
#include<string> class Buffer{ public: //.. const std::string getName() { return m_names; } //... private: std::string m_names; };
Buffer
には、大きなプライベート オブジェクト m_names
が含まれています。このようなプライベート オブジェクトには、getName
などの大きなオブジェクト m_names
を返す公開 getter 関数を使用するのが一般的です。getNames
の戻り値の型は const std::string&
ではなく const std::string
として設定されるため、関数は、参照ではなく、値で大きなオブジェクトを返します。&
が欠落しているにもかかわらず、このコードはコンパイル可能で、正しく機能するため、計算量の多いコピーによる戻しが検出されない可能性があります。同様の非効率性の原因については、計算量の多い値渡し
と範囲ベースの for ループの反復における計算量の多いコピー
を参照してください。修正方法
この欠陥を修正するには、参照を使用することによってオブジェクトを返します。C コードを使用している場合は、値でオブジェクトを返さないためにポインターを使用します。
C++ 関数から参照によってオブジェクトを返すには、関数の戻り値の型を参照として設定します。次に例を示します。
関数#include<string> class Buffer{ public: //.. const std::string& getName() { return m_name; } //... private: std::string m_name; };
getName()
は、大きなオブジェクトm_names
を参照で返します。これは、この関数の戻り値の型が参照であるconst std::string&
のためです。または、値でオブジェクトを返さないためにポインターを使用します。たとえば、
getName()
の戻り値の型をconst std::string*
に設定してから、m_names
のアドレスを&m_names
として返します。ポインターを使用することによって、関数#include<string> class Buffer{ public: //.. const std::string* getName() { return &m_name; } //... private: std::string m_name; };
getName()
はm_names
を値で返さなくなります。この方法は、参照が使用できない C コードで有効です。パフォーマンスの改善の程度は、使用しているコンパイラ、ライブラリ実装、環境によって異なる可能性があります。
例
結果情報
グループ: パフォーマンス |
言語: C | C++ |
既定値: オフ |
コマンド ライン構文: EXPENSIVE_RETURN_BY_VALUE |
影響度: Medium |
バージョン履歴
R2020b で導入