1

私は、そうするのが少し苦痛に思えるときでさえ、const本当にあるべきものを作ることにこの執着を持っています。const

この場合、vector<int>要素を追加できるが、既存の要素を変更できないinが必要です。問題はそれvector<const int>が許可されていないということです。

目的は、クラスのユーザーが変更してはならないものを変更できないようにすることだけではありません(これはconst、メンバー関数のイテレーターによって簡単に実行できます)。それはまた、同じように重要なので、私自身は後で自分のコードで意図していなかったことをしません

私は2つの選択肢を見つけました:

  • deque<const int>代わりに使用してください。

  • このように、実際をラップする独自のベクトルクラスを作成しますvector(ここではこれを行いintますが、実際には一般性のためにテンプレートを使用します)

    class my_vector {
    private:
      std::vector<int> vec;    
    public:
      std::vector<int>::const_iterator cbegin() { return vec.cbegin(); }
      std::vector<int>::const_iterator cend() { return vec.cend(); }
      void push_back(int i) { vec.push_back(i); }
    };
    

これらのアイデア(または他のアイデア)のどれをお勧めしますか?コンパイラーは、2番目の選択肢を、ベクトルを直接使用するのと同じくらい高速なコードに変換しますか?

4

3 に答える 3

1

あなたの執着は理解でき、私は同意しませんが、あなたがそれを本当に差し迫った必要がない限り、必要な努力は努力する価値がないかもしれません。

vector設計要件に基づいてコンテナとして選択したと仮定すると、、dequeまたはその他のタイプに変更することはお勧めしません。それは将来の読者(おそらくあなた自身である)を混乱させるのに役立つだけであり、そうでなければ悪い習慣でもあります。

ラッパーソリューションを使用する場合は、ベクターを変更する可能性のあるすべてのメンバーをオーバーライドして非表示にする必要があります。これは、アクセスと変更の両方に使用されるメソッドが多数あるため、問題になります。彼らは「標準的な」振る舞いに慣れているので、これは将来の読者を混乱させる可能性があります。operator[]at()front()back()vector

ちなみに、deque<const int> foo;よろしいですか?次のエラーが発生します。

error: invalid conversion from 'const void*' to 'void*'

編集私はあなたの質問に完全には答えなかったようです。いずれかを選択する必要がある場合は、ラッパーアプローチを選択します。

于 2012-12-08T13:45:23.393 に答える
1

私は、この種の標準コンテナ-ほぼ正確に-私のニーズに合うケースには、プライベート継承を好みます。パブリック継承は、基本クラスへのポインターを介したスライスまたは非仮想破壊につながります。作曲には余分なタイピングが必要です。

個人の継承と使用はusingあなたの意図をうまく表現します。

次に例を示します。

#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>

class my_vector : private std::vector<int> {
  // Utility type 
  typedef std::vector<int> base;
public:
  // Types I don't need to tweak:
  using base::value_type;
  using base::allocator_type;
  using base::size_type;
  using base::difference_type;
  using base::const_reference;
  using base::const_pointer;
  using base::const_iterator;
  using base::const_reverse_iterator;

  // Types I do need to tweak:
  typedef const_reference reference;
  typedef const_pointer pointer;
  typedef const_iterator iterator;
  typedef const_reverse_iterator reverse_iterator;

  // Constructors
    // Implicit constructors OK
  // Destructors
    // Implicit destructors OK
  // Assignment
    // Implicit assignment OK

  // Methods that I don't need to tweak:
  using base::assign;
  using base::get_allocator;
  using base::empty;
  using base::size;
  using base::max_size;
  using base::reserve;
  using base::capacity;
  using base::clear;
  using base::push_back;
  using base::pop_back;
  using base::swap;

  // Methods I need to tweak
  const_reference at( size_type pos ) const { return base::at(pos); }
  const_reference operator[](size_type pos) const { return base::operator[](pos); }
  const_reference front() const { return base::front(); }
  const_reference back() const { return base::back(); }
  const_iterator begin() const { return base::begin(); }
  const_iterator end() const { return base::end(); }
  const_reverse_iterator rbegin() const { return base::rbegin(); }
  const_reverse_iterator rend() const { return base::rend(); }

  // Methods I need to delete:
    // base::insert;
    // base::erase;
    // base::resize;

};

int main () {
  my_vector m;
  m.push_back(1);
  m.push_back(2);
  m.push_back(3);
  my_vector m2;
  m2 = m;
  std::copy(m2.begin(), m2.end(), std::ostream_iterator<int>(std::cout, "\n"));
}
于 2012-12-08T14:00:21.397 に答える
0

標準のコンテナには何の魔法もありません。標準のコンテナとは異なる特性を持つコンテナが必要な場合は、独自のコンテナを作成してください。標準コンテナの1つが必要なものに近い場合は、それを内部実装として使用します。要するに、my_vector行く方法です。

于 2012-12-08T13:55:32.190 に答える