0

私は小さな「遅延ベクトル」クラス (または遅延ベクトル) を作成しました。これは a のように見え、std::vectora が使用されている場所ならどこでも使用できるはずですstd::vectorが、要素を「遅延」でロードしますn。誰かが element にアクセスするたびに、ディスクからn。(理由は、私のアプリでは、すべての要素がメモリに収まらないためです。)

これがこのLazyVectorクラスですが、そのようなベクトルを使用するメンバー関数には問題がありconstます。以下を参照してください。

template<class T>
class LazyVector {
  std::vector<T> elems_;
  void fetchElem(unsigned n){
    // load the n-th elem from disk into elems_ etc
  }
public:
  const T& operator[](unsigned n) const {
    fetchElem(n); // ERROR: ... discards qualifiers       
    return elems_[n];
  }
  T& operator[](unsigned n) {
    fetchElem(n);
    return elems_[n];
  }
  // and provide some other std::vector functions
};

const私が言ったように、メンバー関数が の要素を要求するときに問題がありLazyVectorます。の性質上LazyVector、要素へのアクセスは ではありません 。つまり、このコンテキストでは禁止されている以下constのベクトルが変更されます。メンバー関数は変更する必要がvecあり、変更することはできません。どうすればこれを解決できますか?fooconst

class Foo {
  LazyVector<const std::string*> vec;
  void fct(int n) const { // fct must be const 
    const std::string* str = vec[n];
    // do something with str 
  }
};
4

6 に答える 6

7

LazyVector クラスの実装では、変更可能なメンバー データまたは const_cast のいずれかを使用できます。したがって、実際には const でなくても、消費するクラスが必要とする const の錯覚を作成できます。

于 2009-02-15T06:40:20.910 に答える
4

elems_ データ メンバーでmutableキーワードを使用します。

于 2009-02-15T06:37:55.083 に答える
3

const 演算子は、オブジェクトが論理的に const であることを示すために使用されます。
データがディスク上にあるという事実は、オブジェクトの状態が変化していないため、実際にデータを保持する作業を別のオブジェクトのキャッシュに委任できます (データが格納される場所は実装の詳細であり、オブジェクトの状態)。

class LazyVector
{
    public:
        int const& operator[](int index) const
        { 
            data->fetchElement(index);
            return data->get(index);
        }
    private:
        std::auto_ptr<LazyDataCache>   data;
};

ここで data はポインターです (スマート ポインターですが、ポインターでもあります)。ポインターが変更されない限り、LazyVector のコストを変更することにはなりません。ただし、データが指すオブジェクトで非 const メソッドを呼び出すことはできます (これは、指すオブジェクトではなく const であるポインターであることを思い出してください)。

于 2009-02-15T08:32:19.023 に答える
2

そのようなもののためのmutableキーワードは for です。キャッシュを変更可能なオブジェクトとしてクラスに入れます。これは、キャッシュがオブジェクトの論理コンテンツ/状態を変更しないように見えるためです (つまり、ベクターの要素またはそのサイズは変更されません)。

constメソッドは、オブジェクトを物理的に変更しないとは述べていません。彼らは、オブジェクトの抽象的な値を変更しないと述べています。抽象化された実装の詳細は、const 関数によって変更される可能性があります。

ミュータブルはこの種のケース用です。ベクターを変更可能にするか、何らかのキャッシュ エントリを含む変更可能なキャッシュ メンバーを追加します。

Anthony Williams によるconst メンバー関数の回答のセマンティクスとは何かをお読みください。

于 2009-02-15T06:39:57.043 に答える
1

次のように宣言elems_mutableます。

mutable std::vector<T> elems_;

他にもできることがありますが、それがサポートされている方法です。

編集:これを行う別の方法は、別のメンバーを追加してコンストラクターに設定することです。

std::vector<T> *mutable_elems_;

mutable_elems_(&elems_)

于 2009-02-15T06:39:08.277 に答える
1

これを行う大雑把な方法は次のようになります

LazyVector* p = const_cast<LazyVector*>(this);
p->fetch();

これを行うにはもっと良い方法があると思います。しかし、これはうまくいきます。

于 2009-02-15T06:42:06.803 に答える