EN JP CN

CL.ASSIGN.NON_CONST_ARG

CL.ASSIGN.NON_CONST_ARG

代入演算子 = に非定数オブジェクトが渡されました

これは、代入演算子のパラメータータイプの選択で、制約がある、または上手くない可能性を通知するクラスレベル (CL) のチェッカーです。クラスレベルのチェッカーは有効な C++ のための Scott Meyer 規則クラス構築に基づいて推奨を通知します。

CL.ASSIGN.NON_CONST_ARG チェッカーは、非定数オブジェクトを演算子 = に渡すクラスを検出します。この種のコードが使用されると、言語構築によっては表現できない場合があります。これらの言語構築が望ましいかそうでないかは議論の余地がありますが、以下の基本テンプレートに従えば、型によらずに言語の一貫性を維持できることが保証されます。

  class MyClass {
  public:
    MyClass& operator=(const MyClass&);
  };

代入演算子が返るときに、*this または演算子の右辺のいずれかを返すことができます。

1   class C{
//...
2   public:
3     C& operator=(const C& rhs){
4      return rhs;
5     }
//...
5   };

これは明示的な const キャストを行わずに const 属性を 'rhs' から削除するため、明らかにコンパイルできません。いずれにせよ、よいアイデアとは言えません。これに対する、すぐにできる (しかし最悪の) 解決策は、'rhs' パラメーターを非定数参照として宣言することです。

1   class C{
//...
2   public:
3     C& operator=(C& rhs){
4      return rhs;
5     }
//...
6   };

これでコードはコンパイルできますが、この解決策ではコンパイラによって作成された一時オブジェクトをクラスに割り当てることが不可能になります。たとえば、次のようになります。

1   class C{
//...
2   public:
3     C& operator=(C&);
4     C(int);
//...
5   };
//...
6    C obj = 10;

この場合は、コンパイラは整数定数の一時オブジェクトを構築し、定数の一時オブジェクトを入力として受け入れる代入演算子を探そうとします。非定数代入演算子のみが存在するため、これは明らかに失敗します。もう一度繰り返しますが、ベストな解決策は、できれば、代入演算子用の簡単で標準的なテンプレートに従うことです。

脆弱性とリスク

この設計では脆弱になることはありませんが、精通していないプログラマーが、"動作はする" が互換性のない言語構築を使用しようと試みて、(C++ コンパイラ出力の通常の複雑度の) ほとんど意味のないコンパイラからの警告に直面するリスクはあります。

脆弱コード例

     
1    class C{
//...
2    public:
3       C& operator=(C& rhs){
4       return rhs; 
5      }
//...
6    }; 

この例では、3 行目で CL.ASSIGN.NON_CONST_ARG エラーが検出されます。これはクラス構築規則に違反しています。

修正コード例

     
1    class C{
//...
2    public:
3      C& operator=(const C& rhs){
4       return *this; 
5      }
//...
6    }; 

修正したコード例では、演算子 = が *this を返し、規則違反を回避します。