2012-07-06 37 views
0

正如标题所说,我尝试以这种方式扩展std :: vector类,如果我删除了一个元素,则该位置的值不是已被删除但实际上设置为NULL(提供间隙)。将std :: vector作为动态数组扩展为NULL对象

template<typename T> 
class FVector : public std::vector<T> { 
    typedef std::vector<T> Base; 

protected: 
    /** The number of elements in the vector */ 
    size_t elementCount; 

    /** 
    * The index of the last element. This field is actually vector's length. 
    * For example when you have a vector like this ["a","b","c"] then the 
    * elementCount would be 3 and lastIndex would be 2 (because indexes are 
    * zero-based). But if you erased two first elements, 
    * leaving [null, null, "c" ] then elementCount=1 (because there is only 
    * one element in the vector!) however lastIndex would still remain 2. 
    * After you erase "c" lastIndex would be set to -1 (so it's enough to 
    * add 1 to lastIndex to determine vector's length. 
    */ 
    int lastIndex; 

private: 
    /** 
    * Returns the index of the last not-null element in the vector, 
    * starting from position position downwards. 
    * 
    * @param position the position from which counting is to be begun. 
    * @return last element before (or on) index <code>position</code> 
    */ 
    int FindLastIndex(int position) { 
     int nLastItem = position; 

     if (position < 0) { 
      return -1; 
     } 

     for (; nLastItem >= 0; nLastItem--) { 
      if (Base::operator[](nLastItem) != NULL) { 
       break; 
      } 
     } 

     return (nLastItem); 
    } 

public: 

    FVector(const T & value = T()) 
    : elementCount(0), lastIndex(-1) { 
    } 

    FVector(int initialCapacity, const T & value = T()) 
    : elementCount(0), lastIndex(-1), 
     std::vector<T>(initialCapacity, value) { 
    } 

    size_t Capacity() const { 
     return Base::size(); 
    } 

    size_t Size() const { 
     return elementCount; 
    } 

    int LastIndex() const { 
     return lastIndex; 
    } 

    void AddElement(const T& obj) { 
     Base::push_back(obj); 

     elementCount++; 
     lastIndex++; 
    } 

    T & ElementAt(int index) { 
     if (index > lastIndex) { 
      // error 
     } 

     return Base::at(index); 
    } 
    void EraseElementAt(int index) throw() { 
     if (index > lastIndex) { 
      std::stringstream ss; 
      ss << index << " > " << lastIndex; 
      throw ArrayIndexOutOfBoundsException(ss.str()); 
     } 

     if (Base::operator[](index) != NULL) { 
      elementCount--; 
      T v = Base::at(index); 
      delete v; 
      Base::at(index) = NULL; 

      if (index == lastIndex) { 
       lastIndex = FindLastIndex(lastIndex - 1); 
      } 
     } 
    } 
}; 

它不像我所期望的那样工作。当我在元素上调用erase()方法时,元素 未设置为NULL。

例如:

class Int { 
    int i; 
public: 
    Int(int v): i(v) { }; 
    ~Int() { } 
}; 

//... 

FVector<Int *> * v = new FVector<Int *>(); 

v->AddElement(new Int(1)); 
v->AddElement(new Int(3)); 
v->AddElement(new Int(5)); 
v->EraseElementAt(0); 
v->EraseElementAt(2); 

// ... 

delete v; 

将导致

[NULL,3]

但我希望它是

[NULL,3,空]

嗯,我不知道这是可能的,我尝试实现。我以为std :: vector类,这是一个动态数组(为什么我应该写我自己的数组类),给我所有的基本知识,我需要实现这样的事情。

任何人都可以对此有所了解,我想我在这里有一些实现问题。

感谢您的帮助!

+0

只是一个愚蠢的问题:你为什么要实现这样的事情? – 2012-07-06 15:34:32

+0

我知道,这个想法可能是愚蠢的,但我有一些想法,我想尝试在一个项目。对我来说这也是一个小练习。对不起,模糊的答案! – 2012-07-06 15:36:57

+5

考虑http://stackoverflow.com/questions/4353203/thou-shalt-not-inherit-from-stdvector及其链接的问题。 – 2012-07-06 15:39:54

回答

3

在你EraseElementAt你有这样的:

 if (index == lastIndex) { 
      lastIndex = FindLastIndex(lastIndex - 1); 
     } 

如果你碰巧删除向量中的最后一个元素(你没有)会缩短矢量(减量lastIndex的)。看起来你想要你的矢量不这样做 - 而你想让矢量为空但不缩短。也许只是把它拿出来。

+0

这很合理,现在看起来更好。 lastIndex应该是向量NOT NULL中最后一个元素的计数器。 – 2012-07-06 15:57:17