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

std::vector cleared without interaction

本文关键字:情况下 清除 交互 vector      更新时间:2023-10-16

我有一个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。这怎么可能呢?

这是一个问题:

class ENGINE_API QuadTree {
    typedef std::vector<QuadTree> ChildContainer;
    ChildContainer children;
在类定义完成之前,

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

换句话说,类不能包含自身的向量。你将不得不重新设计你的类,例如:

  • 切换为智能指针向量,
  • 用pImpl语言实现向量
  • 使用不同的容器,该容器设计用于不完整类型