0

正如标题所说,如果我删除一个元素,我会尝试以这种方式扩展 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;

将导致

[空,3]

但我希望它是

[空,3,空]

好吧,我不知道这是否可能是我试图实现的目标。我认为采用 std::vector 类,它是一个动态数组(那么我为什么要编写自己的数组类)为我提供了实现此类东西所需的所有基础知识。

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

谢谢你的帮助!

4

1 回答 1

3

在你的 EraseElementAt 你有这个:

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

如果您碰巧擦除了向量中的最后一个元素(您这样做了),它将缩短向量(递减 lastIndex)。似乎您希望您的向量不这样做 - 而是您希望向量为空但不缩短。也许只是把这个拿出来。

于 2012-07-06T15:39:54.820 回答