1. ホーム
  2. c++

C++によるリファクタリング 11

2023-09-23 02:26:08

質問

c++ によって提供される新しいツールセットを考えると、コードの簡略化、表現力、効率性を目指す多くのプログラマは、古いコードをざっと読んで、その目標を達成するために微調整を行います (無意味なものもあれば、成功するものもあります)。そのような労働にあまり時間を費やさないようにし、押し付けがましくない、自己完結した変更を行う一方で、ベストプラクティスは何でしょうか?

明らかなものを除外してみましょう。

  • 使用する 自動 を使って、イテレータベースのループを実行します。

    for (std::vector<foo>::const_iterator it(lala.begin()), ite(lala.end()); it != ite;     
    ++it);
    // becomes
    for (auto it(lala.cbegin()), ite(lala.cend()); it != ite; ++it);
    
    
  • 使用方法 ネクタイ は、C 言語風のコード列を生成するだけの多重代入のために ( 構造体に複数の値を一度に代入する方法は? )

    a = 1;
    b = 2; 
    c = 3;
    d = 4; 
    e = 5;
    // becomes
    std::tie(a, b, c, d, e) = std::make_tuple(1, 2, 3, 4, 5);
    
    
  • クラスを継承できないようにするには、そのクラスを "final" と宣言し、そのような動作を実現したコードを削除します。 http://www.parashift.com/c++-faq/final-classes.html

  • コンストラクタやデストラクタを private 宣言するのではなく、明示的に隠すために delete キーワードを使用します (例: ヒープベースのオブジェクトやコピー不可能なオブジェクトを作成するコードなど)。

  • 単一のSTLアルゴリズムの実行を容易にするためだけに作成された些細なファンクタを ラムダ 関数に変更します(コードの散らかりを減らす以外に、インライン呼び出しが保証されます)。

  • オブジェクトの RAII ラッピングを単純化するために スマートポインタ

  • bind1st、bind2ndを廃止し、単に バインド

  • 型特性 (Is_ptr_but_dont_call_for_const_ptrs<> など :) の手書きコードを、以下の標準コードに置き換える。 < type_traits >

  • STLで実装された機能性のためのboostヘッダを含むことをやめました(BOOST_STATIC_ASSERT vs static_assert)。

  • クラスへの移動セマンティクスの提供(ただし、これはダーティ/クイック/イージーな変更として適格ではないでしょう)

  • 使用方法 nullptr を使用し、ポインタのコンテナをオブジェクト型にキャストされた 0 で埋めていたコードを削除してください。

    std::vector<foo*> f(23);
    for (std::size_t i(0); i < 23; ++i)
    { f[i] = static_cast<foo*>(0); }
    // becomes
    std::vector<foo*> f(23, nullptr);
    
    
  • ベクターデータのアクセス構文をクリアする

    std::vector<int> vec;
    &vec[0];    // access data as a C-style array
    vec.data(); // new way of saying the above
    
    
  • throw()を noexcept (非推奨の例外指定を避ける以外に、速度面での利点があります。 http://channel9.msdn.com/Events/GoingNative/2013/An-Effective-Cpp11-14-Sampler @ 00.29.42)

    void some_func() noexcept; // more  optimization options
    void some_func() throw();  // fewer optimization options
    void some_func() ;         // fewer optimization options
    
    
  • コンテナ内の tempory をプッシュして、オプティマイザがコピーを消去してくれることを期待するようなコードを emplace" 関数に置き換えることで、引数を完全に転送し、テンポラリなしでオブジェクトをコンテナに直接構築します。

    vecOfPoints.push_back(Point(x,y,z)); // so '03
    vecOfPoints.emplace_back(x, y, z);   // no copy or move operations performed
    
    

最新情報

Shafik Yaghmour氏の回答 の回答は、聴衆に最も受け入れられたとして、当然のことながら賞金を授与されました。

R Sahu氏の回答 は私が認めたもので、なぜなら の組み合わせ を捉えているからです。 リファクタリングの精神 : コードをより明確に、よりきれいに、よりシンプルに、よりエレガントにすることです。

どのように解決するのですか?

デリゲートコンストラクタとクラス内メンバ初期化子を追加する。

委譲コンストラクタとクラス内初期化の使用による簡素化

C++03で。

class A
{
  public:

    // The default constructor as well as the copy constructor need to 
    // initialize some of the members almost the same and call init() to
    // finish construction.
    A(double data) : id_(0), name_(), data_(data) {init();}
    A(A const& copy) : id_(0), name_(), data_(copy.data_) {init();}

    void init()
    {
       id_ = getNextID();
       name_ = getDefaultName();
    }

    int id_;
    string name_;
    double data_;
};

C++11で。

class A
{
  public:

    // With delegating constructor, the copy constructor can
    // reuse this constructor and avoid repetitive code.
    // In-line initialization takes care of initializing the members. 
    A(double data) : data_(data) {}

    A(A const& copy) : A(copy.data_) {}

    int id_ = getNextID();
    string name_ = getDefaultName();
    double data_;
};