2

I was surprised to find out the vector::erase move elements on calling erase . I thought it would swap the last element with the "to-be-deleted" element and reduce the size by one. My first reaction was : "let's extend std::vector and over-ride erase()" . But I found in many threads like " Is there any real risk to deriving from the C++ STL containers? ", that it can cause memory leaks. But, I am not adding any new data member to vector. So there is no additional memory to be freed. Is there still a risk?

Some suggest that we should prefer composition over inheritance. I can't make sense of this advice in this context. Why should I waste my time in the "mechanical" task of wrapping every function of the otherwise wonderful std::vector class.? Inheritance indeed makes the most sense for this task - or am I missing something?

4

4 に答える 4

11

必要なことを行うスタンドアロン関数を作成してみませんか。

template<typename T>
void fast_erase(std::vector<T>& v, size_t i)
{
   v[i] = std::move(v.back());
   v.pop_back(); 
}

ただし、すべてセス・カーネギーの功績です。私はもともと「std::swap」を使用していました。

于 2012-04-14T20:35:19.877 に答える
4

デリケートな問題。あなたが違反している最初のガイドラインは、「継承はコードの再利用のためのものではありません」です。2 つ目は、「標準ライブラリ コンテナーから継承しない」です。

しかし: あなたが保証できるなら、誰もあなたをあなたが良い人unordered_vector<T>として使うことは決してないでしょう. vector<T>ただし、誰かがそうすると、メンバーの数に関係なく、結果が未定義および/または恐ろしいものになる可能性があります(完全に機能しているように見えても、未定義の動作です!)。

継承を使用することもできますが、ラッパーを作成したり、多くのステートメントをprivate使用してメンバー関数をプルしたりすることから解放されるわけではありません。using


using編集:ステートメントで私が意味することはこれです:

class Base {
  public:
    void dosmth();
};

class Derived : private Base {
  public:
    using Base::dosmth;
};

class Composed {
  private:
    Base base;
  public:
    void dosmth() {return base.dosmth(); }
};

のすべてのメンバー関数でこれを行うことができますstd::vector。ご覧のとおりDerived、コードは より大幅に少なくなっていますComposed

于 2012-04-14T20:39:00.390 に答える
3

継承のリスクは、次の例にあります。

std::vector<something> *v = new better_vector<something>();
delete v;

仮想デストラクタのない基本クラスへのポインタを削除したため、問題が発生します。
ただし、次のようにクラスへのポインターを常に削除する場合:

better_vector<something> *v = new better_vector<something>();
delete v;

または、ヒープに割り当てないでください。危険はありません。デストラクタで親デストラクタを呼び出すことを忘れないでください。

于 2012-04-14T20:32:26.897 に答える
2

最後の要素を「削除する」要素と交換し、サイズを1つ減らすと思いました。

vector::erase は要素の順序を維持しますが、最後の要素を消去された要素に移動し、サイズを 1 減らしません。ベクトルは配列を実装するため、要素の順序を維持し、同時に消去する O(1) 方法はありません (最後の要素を削除しない限り)。

要素の順序を維持することが重要でない場合は、ソリューションが問題ありません。それ以外の場合は、他のコンテナーを使用することをお勧めします (たとえば、二重リンク リストを実装する list )

于 2012-04-14T20:52:19.023 に答える