2

私は明らかにたくさんのクラスを持っている非常に大きなコードベース(3M以上)で作業していますが、それらのほとんどはコンストラクタで初期化リストを使用しません。コンストラクタ本体(コードのいくつかは長い時間前に書かれていたので、これはデファクトスタンダードになっています)。おそらく、これらはコンパイラによって最適化されていますが、実際はそうではありません。初期化リストを使用するリファクタリングコンストラクタ

私は初期化リストの使用を促進しようとしていますが、最新のコードベースが必要です。自動的にこれを行うツールはありますか?クラスを指し、すべてのm_var = 0;行を見つけて、それらを初期化リストに移動します(必要に応じて作成します)。

ボディ内初期化を初期化リストに変換するだけでなく、メンバ変数が正しい順序で初期化されていることを確認する方法がありますか(クラスのヘッダファイルで定義されている順序と同じですか? CppCheckがこれを拾うだろうが、それはしていないようことを期待していた。

+1

2番目の部分については、GCCには '-Wreorder'があります。 – Biffen

+0

@BiffenはVisual Studio 2012を実行しますか?それが私が使っているものです。 – fwgx

+1

私が知っているわけではありませんし、すばらしいGoogleは何もしませんでした。私はそれについてもっと研究するためにそれをあなたに任せます。 – Biffen

答えて

2

こんにちは、私はcppcheckの開発者です。

Cppcheckもオーダーを不整合のチェックを持っている。しかし、それは決定的チェックです。

例:

class Fred { 
public: 
    Fred() : y(0), x(0) {} 
    int x; 
    int y; 
}; 

Cppcheck出力:

[email protected]:~/cppcheck$ ./cppcheck --enable=style --inconclusive 1.cpp 
Checking 1.cpp ... 
[1.cpp:3] -> [1.cpp:4]: (style, inconclusive) Member variable 'Fred::x' is in the wrong place in the initializer list. 

私たちの簡単なチェックだけでいつでもオーダーの不一致を警告します。それが理由ではありません。上のコードでは、上のコードのすべてのメンバがintであり、すべての初期化子が定数リテラルなので、初期化順序は実際には重要ではありません。

1

OPのコードベースのサイズと同じように、必要なものはprogram transformation system (PTS)です。これは、ターゲット言語ソースファイルをコンパイラデータ構造(通常はAST)に解析し、ASTに変換を適用し、修正されたプログラムの元のコメントを含む有効なソースコードを再生成することができるツールです。 PSTをのリファクタリングのツールと考えてください。

良いPTSは、あなたがソース・ソースは、フォームの変換書くようになる:

when you see *this*, replace it by *that* if *condition* 

このは、ターゲット言語の構文で表現されていることをこのソースコードが明示的な構文と一致する場合にのみ一致します。 [これらは文字列一致ではありません。彼らはASTで動作するので、レイアウトは一致する能力には影響しません]。

rule move_to_initializer(constructor_name:IDENTIFIER, 
         arguments: argument_list, 
         initializer_list: initializer, 
         member_name:IDENTIFIER, 
         initializer_expression: expression, 
         statements: statement_list 
         ): constructor -> constructor = 
    " \constructor_name(\arguments): \initializer_list 
      { \member_name = \initializer_expression ; 
      \statements } " 
    -> " \constructor_name(\arguments): \initializer_list, \member_name(\initializer_expression) 
      { \statements } "; 

The syntax of these rules/patterns for our DMS Software Reengineering Toolkit is explained here

あなたはこのようになりますキーのルールを必要としています。 DMSは、C++を処理できる唯一のソースからソースへのPTSです。 MSVS方言を扱うことさえできます]。

おそらく必要な「の条件」は、あなたのコンストラクタが悪用されていないことを前提に、メンバー名が実際にクラスのメンバーであることをチェックしています。

あなたのコンストラクタは、任意の初期化子リストを持っていない可能性がありますので、あなたが必要なものを紹介するヘルパールールが必要になります。

rule move_to_initializer(constructor_name:IDENTIFIER, 
         arguments: argument_list, 
         member_name:IDENTIFIER, 
         initializer_expression: expression, 
         statements: statement_list 
         ): constructor -> constructor = 
    " \constructor_name(\arguments) 
      { \member_name = \initializer_expression ; 
      \statements } " 
    -> " \constructor_name(\arguments): \member_name(\initializer_expression) 
      { \statements } "; 

      { \member_name = \e ; } " 

必ずあなたが他の特殊なケースをカバーするために追加のルールを必要とするが、それはより多くすべきではありませんいくつか。オーダー・オブ・初期設定にチェックについて

、あなたは(DMS)のパターンを使用して、このようなチェックをトリガすることができます:

彼らがある場合は文句を言い順序をチェックする補助メタ述語を、必要と
pattern check_initializer_order(constructor_name:IDENTIFIER, 
         initializer_list: initializer, 
         statements: statement_list 
         ): constructor = 
    " \constructor_name(): \initializer_list, 
      { \statements } " 
      if complain_if_not_ordered(constructor_name,initializer_list); 

秩序だった。述部が対応するクラスをルックアップしてメンバーの順序を検査できるようにするには、constructor_nameが必要です。 [DMSはmeans to access a symbol tableにこの情報を提供します]。

rule order_initializers(constructor_name:IDENTIFIER, 
         arguments: argument_list, 
         initializer_list_prefix: initializer, 
         initializer_list_suffix: initializer, 
         member1_name:IDENTIFIER, 
         initializer1_expression: expression, 
         member2_name:IDENTIFIER, 
         initializer2_expression:expression,        
         statements: statement_list 
         ): constructor -> constructor = 
    " \constructor_name(\arguments): 
      \initializer_list_prefix, 
      \member1_name(\initializer1), 
      \member2_name(\initializer2), 
      \initialize_list_suffix 
      { \statements } " 
    -> 
    " \constructor_name(\arguments): 
      \initializer_list_prefix, 
      \member2_name(\initializer2), 
      \member1_name(\initializer1), 
      \initialize_list_suffix 
      { \statements } " 
     if is_wrong_order(constructor_name,member1_name,member2_name); 

このルールは、基本的に初期化子をソート:

また、あなたは、単にそれらを別の書き換えルールを使用して順序を変更することがあります。 [これはバブルソートですが、イニシャライザのリストは長くならない傾向があり、コンストラクタごとに一度だけ実行します。]このルールは、コンストラクタ本体からすべてのイニシャライザを削除した後に実行します前述のルール。

関連する問題