2

ベクトルに似たクラスを作成しています。独自のアルゴリズムを使用して、データが実際に保存される場所と方法を決定します。ユーザーの観点からは、通常のベクトルと同じように機能します。

内部的には、重複する値を複数回保存しないことでメモリを節約しようとします。同じ値がベクトルに複数回プッシュされると、インデックスを使用して派手なダンスムーブが実行されますが、実際の値は1回しか保存されません。

operator []をオーバーロードすると、インデックス引数が「実際の」インデックスに変換されるため、データが実際に格納されている場所にアクセスできます。

ユーザーが次のような要素にアクセスしようとした場合:

int i = svec[8];

8を「実際の」インデックスに変換し、正しい要素にアクセスすることで、正しい要素が返されます。

ユーザーが次のような値を割り当てようとすると、問題が発生します。

svec[8] = 1;

値8は再び「実際の」インデックスにカバーされ、要素への参照は。によって返されoperator[]()ます。ただし、複数のインデックスがその要素にマッピングされている可能性があります。参照を返し、それを変更できるようにすると、他のインデックスの値を変更するという望ましくない副作用が発生します。

要素を値で返すだけでは、operator[]を使用して値を割り当てることはできません。

operator[]()で、新しい要素を作成し、インデックスを使用してさらに派手なダンスムーブを実行し、新しい要素への参照を返すことができるように、操作が要素の値を変更する予定があるかどうかを知りたいです。

このようなことは可能ですか?そうでない場合は、値で返すことを余儀なくされているようです。そのため、ユーザーは[]を使用して値を変更できません。

4

2 に答える 2

3

クラスにメソッドがchange_elementあり、変更時に全員がこの関数を呼び出しているとしたら、それは簡単でしょう。

template <typename T>
struct my_vec {
  T& change_element(int index, T new_value)
  { ... }
};

さて、アイデアはoperator[]あなたのためにこの仕事をするプロキシクラスを返すことです。

  // inside my_vec:
  struct proxy {
    my_vec *vec;
    int index;

    T& operator=(T o)
    { return vec->change_element(index, std::move(o)); }

    operator T() const { return (*const_cast<my_vec const*>(vec))[index]; }
  };

  proxy operator[](int i) { return proxy{this, i}; }
  T const& operator[](int i) const { ... }

オーバーヘッドはありません。すべての一般的なコンパイラは、プロキシ要素を最適化する必要があります。

このトリックは、STLでも使用されていvector<bool>ます。より完全な例については、これを確認してください。

于 2012-11-24T14:23:07.967 に答える
0

変換演算子を使用してクラスを型に戻し、要素を変更する必要があることをベクトルに通知する割り当て演算子を返すことができます。

于 2012-11-24T14:16:25.880 に答える