C++ 四叉树在C+中的实现+;:引发异常读取访问冲突

C++ 四叉树在C+中的实现+;:引发异常读取访问冲突,c++,sfml,quadtree,C++,Sfml,Quadtree,我试图在C++中实现四叉树,但是我有一个读访问违规,我花了几个小时试图找出。注意,我将所有成员变量公开,只是为了调试 每当我试图细分一个象限(即根象限)时,我得到 引发异常:读取访问冲突。 std::\u Vector\u alloc>::\u Myend(…)返回0xDD9 四元树由指向连续四元数组的指针以及点组成。这些指针被传递到每个象限,因此它们可以在不复制的情况下写入象限 我做错了什么+你能提出改进建议吗 这是我的四叉树类: class Quadtree { private:

我试图在C++中实现四叉树,但是我有一个读访问违规,我花了几个小时试图找出。注意,我将所有成员变量公开,只是为了调试

每当我试图细分一个象限(即根象限)时,我得到

引发异常:读取访问冲突。 std::\u Vector\u alloc>::\u Myend(…)返回0xDD9

四元树由指向连续四元数组的指针以及点组成。这些指针被传递到每个象限,因此它们可以在不复制的情况下写入象限

我做错了什么+你能提出改进建议吗

这是我的四叉树类:

  class Quadtree
{
private:

    Boundary rootBoundary;
public:
    std::vector<Ball>* dataPtr = nullptr;
    std::vector<Quadrant>* quadrantPtr = nullptr;
    Quadtree(const Boundary& b);


};

    Quadtree::Quadtree(const Boundary& bo)
    :rootBoundary(bo)
{
    std::vector<Ball>* bPtr = new std::vector<Ball>;
    std::vector<Quadrant>* qPtr = new std::vector<Quadrant>;
    quadrantPtr = qPtr;
    dataPtr = bPtr;


    Quadrant Root(bo, quadrantPtr, dataPtr);

}
类四叉树
{
私人:
边界根边界;
公众:
std::vector*dataPtr=nullptr;
std::vector*quadrantPtr=nullptr;
四叉树(const-Boundary&b);
};
四叉树::四叉树(常量边界和bo)
:根边界(bo)
{
std::vector*bPtr=新的std::vector;
std::vector*qPtr=新的std::vector;
象限ptr=qPtr;
dataPtr=bPtr;
象限根(bo、象限PTR、数据PTR);
}
象限树包含所有象限以及数据存储

下面是象限类:

 class Quadrant
    {
    private:

    public:
        std::vector<Quadrant>* quadrantPtr = nullptr;
        std::vector<Ball>* dataPtr = nullptr;
        Boundary m_boundary;
        std::vector<unsigned int> elementIndex;
        int first_child_index = -1;
        int count = 0;

        Quadrant(Boundary b, std::vector<Quadrant>* qPtr, std::vector<Ball>* dPtr);
        void Subdivide();
        bool Insert(Ball* Ball);
        void Display(sf::RenderWindow& myWindow);

    };


Quadrant::Quadrant(Boundary b, std::vector<Quadrant>* qPtr, std::vector<Ball>* bPtr)
    :dataPtr(bPtr), quadrantPtr(qPtr), m_boundary(b)
{
    qPtr->push_back(*this);
}
void Quadrant::Subdivide()
{
    float cx = m_boundary.m_Centre.x;
    float cy = m_boundary.m_Centre.y;
    float qw = m_boundary.m_halfSize.x / 2;
    float qh = m_boundary.m_halfSize.y / 2;

    sf::Vector2f halfSize{ qw, qh };
    first_child_index = quadrantPtr->size();

    Boundary NE(sf::Vector2f{ cx + qw, cy - qh }, halfSize);
    Quadrant NEQ(NE, quadrantPtr, dataPtr);
    Boundary NW(sf::Vector2f{ cx - qw, cy - qh }, halfSize);
    Quadrant NWQ(NW, quadrantPtr, dataPtr);
    Boundary SE(sf::Vector2f{ cx + qw, cy + qh }, halfSize);
    Quadrant SEQ(SE, quadrantPtr, dataPtr);
    Boundary SW(sf::Vector2f{ cx - qw, cy + qh }, halfSize);
    Quadrant SWQ(SW, quadrantPtr, dataPtr);


}

bool Quadrant::Insert(Ball* ball)
{
    if (!m_boundary.ContainsPoint(*ball))
    {
        return false;
    }
    if (count < 4)
    {
        elementIndex.push_back(dataPtr->size());
        count++;
        return true;
    }
    else
    {
        if (first_child_index == -1)
        {
            std::cout << "subdividing" << std::endl;
            Subdivide();
        }
        for (int i = 0; i < 4; i++)
        {
            if (quadrantPtr->at(first_child_index + i).Insert(ball))
            {
                return true;
            }
        }
    }

}

void Quadrant::Display(sf::RenderWindow& myWindow)
{
    myWindow.draw(m_boundary.boundary);
    if (first_child_index != -1)
    {
        for (int i = 0; i < 4; i++)
        {
            quadrantPtr->at(first_child_index + i).Display(myWindow);
        }
    }
}
类象限
{
私人:
公众:
std::vector*quadrantPtr=nullptr;
std::vector*dataPtr=nullptr;
边界m_边界;
向量元素索引;
int first_child_index=-1;
整数计数=0;
象限(边界b,标准::向量*qPtr,标准::向量*dPtr);
void Subdivide();
bool镶块(球*球);
无效显示(sf::RenderWindow和myWindow);
};
象限::象限(边界b,标准::向量*qPtr,标准::向量*bPtr)
:数据PTR(bPtr)、象限PTR(qPtr)、m_边界(b)
{
qPtr->推回(*此);
}
空象限::细分()
{
浮动cx=m_边界.m_中心.x;
浮动cy=m_边界.m_中心.y;
浮动qw=m_边界。m_半尺寸。x/2;
浮动qh=m_边界。m_半尺寸。y/2;
向量2f半尺寸{qw,qh};
第一个子索引=象限ptr->size();
边界NE(sf::Vector2f{cx+qw,cy-qh},半尺寸);
象限NEQ(NE、象限PTR、数据PTR);
边界NW(sf::Vector2f{cx-qw,cy-qh},半尺寸);
象限NWQ(NW、象限PTR、数据PTR);
边界SE(sf::Vector2f{cx+qw,cy+qh},半尺寸);
象限顺序(SE、象限PTR、数据PTR);
边界SW(sf::Vector2f{cx-qw,cy+qh},半尺寸);
象限SWQ(SW、象限PTR、数据PTR);
}
布尔象限::插入(球*球)
{
如果(!m_boundary.ContainsPoint(*ball))
{
返回false;
}
如果(计数<4)
{
elementIndex.push_back(dataPtr->size());
计数++;
返回true;
}
其他的
{
如果(第一个子索引==-1)
{
std::cout at(第一子索引+i)。显示(myWindow);
}
}
}
以下是表示象限AABB的边界类:

class Boundary
{
private:

public:
    sf::Vector2f m_Centre;
    sf::Vector2f m_halfSize;
    sf::RectangleShape boundary;
    Boundary();
    Boundary(const sf::Vector2f& centre, const sf::Vector2f& halfSize);
    bool ContainsPoint(const Ball& ball) const;
    ~Boundary();

};

Boundary::Boundary()
{

}
Boundary::Boundary(const sf::Vector2f& Centre, const sf::Vector2f& HalfSize)
    :m_Centre(Centre), m_halfSize(HalfSize)
{
    boundary.setSize(m_halfSize + m_halfSize);
    boundary.setOrigin(m_halfSize);
    boundary.setPosition(m_Centre);
    boundary.setFillColor(sf::Color::Transparent);
    boundary.setOutlineColor(sf::Color::White);
    boundary.setOutlineThickness(2);
}
bool Boundary::ContainsPoint(const Ball& ball) const
{
    bool contains = false;
    if (ball.ball.position.x > m_Centre.x - m_halfSize.x && ball.ball.position.x < m_Centre.x + m_halfSize.x)
    {
        if (ball.ball.position.y > m_Centre.y - m_halfSize.y && ball.ball.position.y < m_Centre.y + m_halfSize.y)
        {
            contains = true;
        }
    }
    return contains;
}
类边界
{
私人:
公众:
sf::维克托2F m_中心;
矢量2F m_半尺寸;
矩形边界;
边界();
边界(常数sf::矢量2F和中心,常数sf::矢量2F和半尺寸);
bool ContainsPoint(常数球和球)常数;
~Boundary();
};
边界::边界()
{
}
边界::边界(常数sf::矢量2F和中心,常数sf::矢量2F和半尺寸)
:m_中心(中心),m_半码(半码)
{
边界.设置大小(m_半尺寸+m_半尺寸);
边界。设置原点(m_半尺寸);
边界。设置位置(m_中心);
边界.setFillColor(sf::Color::Transparent);
边界。setOutlineColor(sf::Color::White);
边界。设置轮廓厚度(2);
}
边界::包含点(常量球和球)常量
{
bool-contains=false;
if(ball.ball.position.x>m_center.x-m_halfSize.x&&ball.ball.position.xm_center.y-m_halfSize.y&&ball.ball.position.y
您的
根目录是构造函数的本地目录。也就是说,它就在
四叉树
构造的末尾被销毁。将其改为类成员

另外,您不需要使用
new
创建向量,它们本身基本上就是指针。也让他们成为类成员,并使用
&
获取要传递到
象限的地址(或传递引用)


注意:成员顺序很重要,这是它们初始化的顺序。

能否添加注释以显示出现错误的行?请发布注释。使用类的
main
函数在哪里?还有,为什么这些指针是:
std::vector*dataPtr=nullptr;std::vector*quadrantPtr=nullptr?为什么不简单地
std::vector
std::vector
?但是
push_back(*这个)
在销毁
象限之前复制它。所以这不是问题,
Root
被破坏了,对吗?我的意思是,他们都被摧毁了。只要看看象限::细分()
。即使是
象限
也会复制其
边界
对象。也许问题是它们根本就不是复制品?这个答案缺少对实际问题的描述。哎哟,你没有注意到你复制了一个部分构造的对象而没有引用。但那是UB IIRC,我不知道这些函数怎么称呼<例如,代码>象限::插入
需要非常小心。实际上,如果派生类构造函数尚未执行,则在构造函数中分配
*此
将无法以定义良好的方式工作。在定义继承自
象限的类之前,很可能不会产生黑洞或任何奇怪的东西。