std :: vector在没有交互的情况下清除

时间:2014-03-26 23:01:42

标签: c++ vector

我遇到了std::vector被清除的问题,但我无法弄清楚在哪里。我花了很多时间来调试这个问题,并且不能在我的生活中找到它被清除的地方。

代码:

    class ENGINE_API QuadTree {
    private:
        typedef std::unordered_set<QuadTreeObject*> EntityContainer;
        typedef std::vector<QuadTree> ChildContainer;

        const static int MAX_OBJECTS = 5;
        AABB bounds;

        ChildContainer children;
        EntityContainer entities;
        EntityContainer allEntities;

        // Internal methods
        void split();

        int getIndex(const AABB&)const;

        template <class T>
        void merge(T& one, const T& two) {
            one.insert(two.begin(), two.end());
        }
        // End Internal methods
    public:
        QuadTree(AABB bounds) : bounds(bounds), children(), entities(), allEntities() {
            children.reserve(4);
        }

        // Base
        void clear() {
            entities.clear();
            allEntities.clear();
            children.clear();
        }

        void insert(QuadTreeObject*);

        void remove(QuadTreeObject*, const AABB&);

        // Not the source, I've removed this and it still works fine (Nothing uses this method)
        ChildContainer& getChildren() {
            return children;
        }

        AABB& getBounds() {
            return bounds;
        }

        QuadTree getLowestRoot(const AABB& aabb)const {
            int index = getIndex(aabb);
            if (index == -1 || children.empty()) {
                return *this;
            }
            return children.at(index).getLowestRoot(aabb);
        }

        const EntityContainer& getAll()const {
            return allEntities;
        }
        // End Base
    };

void QuadTree::split() {
    children.clear(); // supposed to be there

    double width = (bounds.getWidth() / 2);
    double height = (bounds.getHeight() / 2);

    children.push_back(QuadTree(AABB(bounds.min.x + width, bounds.min.y, width, height)));
    children.push_back(QuadTree(AABB(bounds.min.x, bounds.min.y, width, height)));
    children.push_back(QuadTree(AABB(bounds.min.x, bounds.min.y + height, width, height)));
    children.push_back(QuadTree(AABB(bounds.min.x + width, bounds.min.y + height, width, height)));

    auto it = entities.begin();
    while (it != entities.end()) {
        int index = getIndex((*it)->getAABB());
        if (index != -1) {
            children.at(index).insert(*it);
            it = entities.erase(it);
        }
        else {
            it++;
        }
    }
}

int QuadTree::getIndex(const AABB& aabb)const {
    // Fits in top
    bool topQuadrant = aabb.max.y < aabb.horzMid;
    // Fits in botom
    bool bottomQuadrant = aabb.min.y > aabb.horzMid;

    // Fits in left
    if (aabb.max.x < aabb.vertMid) {
        if (topQuadrant) {
            return 1;
        }
        else if (bottomQuadrant) {
            return 2;
        }
    }
    // Fits in right
    else if (aabb.min.x > aabb.vertMid) {
        if (topQuadrant) {
            return 0;
        }
        else if (bottomQuadrant) {
            return 3;
        }
    }

    return -1;
}

void QuadTree::insert(QuadTreeObject* object) {
    AABB aabb = object->getAABB();

    allEntities.insert(object);

    if (children.empty()) {
        if (entities.size() <= MAX_OBJECTS) {
            entities.insert(object);
            return;
        }
        split();
    }

    int index = getIndex(aabb);
    if (index != -1) {
        children.at(index).insert(object);
    }
    else {
        entities.insert(object);
    }
}

void QuadTree::remove(QuadTreeObject* object, const AABB& aabb) {
    if (!allEntities.erase(object)) {
        return;
    }

    if (!entities.erase(object)) {
        if (!children.empty()) {
            int index = getIndex(aabb);

            if (index != -1) {
                children.at(index).remove(object, aabb);
            }
            else {
                throw std::logic_error("Can't be in allEntities but not entities!");
            }
        }
        else {
            throw std::logic_error("Can't be in allEntities but not entities!");
        }
    }
}

调用split方法时,children.size()返回4,但到达insert时,它再次为0。这怎么可能?

1 个答案:

答案 0 :(得分:2)

这是一个问题:

class ENGINE_API QuadTree {
    typedef std::vector<QuadTree> ChildContainer;

    ChildContainer children;
在完成类定义之前,

QuadTree是一个不完整的类型。如果您使用std::vector类型不完整,则行为未定义。

换句话说,一个类不能包含它自己的向量。你将不得不重新设计你的课程,例如:

  • 切换到智能指针的向量,
  • 在pImpl习语中实现向量
  • 使用旨在处理不完整类型的其他容器