2017-11-06 6 views
1

背景:このC++メソッドを簡略化できますか?

gap bufferアルゴリズムは、一致するカスタムイテレータを持つSTLコンテナとして実装しています。 Bufferクラスには、他のメンバーの中に、ギャップの開始と終了をそれぞれ表す2つの内部ポインタ_gapStart_gapEndがあります。

BufferIteratorには、反復処理中のBufferクラスへの参照である_bufferと、バッファ内の現在の位置である_posという2つのメンバがあります。通常のイテレータと異なる点は、バッファを前後に移動するときにギャップをスキップすることです。

この目的のために、operator+=(他のすべての反復子算術演算子はそれに関して定義されています)を実装する以下のコードを持っています。このコードは機能しますが、私はそれをもっと簡単にすることができると感じています。

BufferIterator& operator+=(const difference_type& n) { 
    auto count = n; 

    if (count >= 0) { 
     while (count--) { 
      ++_pos; 
      if (_pos == _buffer._gapStart) { 
       _pos += (_buffer._gapEnd - _buffer._gapStart); 
      } 
     } 
    } else { 
     while (count++) { 
      --_pos; 
      if (_pos == _buffer._gapEnd) { 
       _pos -= (_buffer._gapEnd - _buffer._gapStart); 
      } 
     } 
    } 

    return *this; 
} 

ですので、以下のバージョンに置き換えます。しかし、それは動作しません。 segfaultが発生します。どうして?それは私には完全に同等でなければならないと思われ、なぜそうではないのか分かりません。

BufferIterator& operator+=(const difference_type& n) { 

    if (n >= 0) { 
     _pos += n; 
     if (_pos >= b._gapStart) { 
      _pos += (b._gapEnd - b._gapStart); 
     } 
    } else { 
     _pos -= n; 
     if (_pos <= b._gapEnd) { 
      _pos -= (b._gapEnd - b._gapStart); 
     } 
    } 

    return *this; 
} 

誰でもこのことを理解できますか?バージョン1を実装する簡単な方法はありますか、それとも本当にそれを実装する最良の方法ですか?

Btw文脈でコードを見ることができれば、私の簡単なエディタはon Githubです。

+0

BufferIterator& operator+=(const difference_type& n) { auto count = n; if (count >= 0) { while (count--) { ++_pos; if (_pos == _buffer._gapStart) { _pos = _buffer._gapEnd; } } } else { while (count++) { --_pos; if (_pos == _buffer._gapEnd) { _pos = _buffer._gapStart; } } } return *this; } 

、ループを削除するには、あなたのコードは次のようになります。 codereviewと私は貴重なフィードバックを持っていますが、このビットではありません。なぜ私は2つのバージョンが同等ではないのかを理解したいと思っています。私はそのような疑問は、SOのbailiwickの方が多いと思っていました。 – Jaldhar

+1

2番目のバージョンにバグがあります。 '_gapStart = 2;を考えてください。 _gapEnd = 4; pos = 10; n = 10; '今は新しいposは何ですか? PSこれは単体テストが捕まえるべきものです。 –

+0

最初の例では、 '_pos + =(_buffer._gapEnd - _buffer._gapStart);の後にbreak文を置かないでください。複数のバッファを反復処理している場合を除きます。あなたの現在のコードでは分かりません – smac89

答えて

3

最初のバージョンはそのように単純化することができる。全体としては、クラスのためのコードが上に投稿されました@PaulRooney

BufferIterator& operator+=(const difference_type& n) { 
    if (n >= 0) { 
     if (_pos < b._gapStart && b._gapStart <= _pos + n) { 
      _pos += b._gapEnd - b._gapStart; 
     } 
    } else { 
     if (_pos + n <= b._gapEnd && b._gapEnd < _pos) { 
      _pos -= (b._gapEnd - b._gapStart); 
     } 
    } 
    _pos += n; 
    return *this; 
} 
+0

ありがとうございます。私はあなたの2番目のバージョンを使用しました。小さな最適化を行い、各if/elseブロックの最後の行を削除し、戻り前に '_pos + = n; 'に置き換えました。 – Jaldhar

+0

@Jaldhar、戻り値の前に '_pos + = n'があなたの質問に元々あったものと同じでないことを確認するだけです。 'npos = 0'の場合は' n'を追加し、そうでない場合は 'n'を減算するので、元のコード(と結果としてJarod42のコード)は' npos 'の符号に関係なく '_pos'を増加させます。 nは負の数なので、 'abs(n)'を追加しました。この最適化を行うと、2番目のケースでは 'pos'が減少します。それがあなたが期待しているものならば、このディテールに注意を喚起したいだけです。 – FreeNickname

+0

@FreeNicknameはいこれは期待された動作でした。私が最初にそのコードを書いたとき、私は本当にまっすぐ考えていなかったように見えます! – Jaldhar

関連する問題