quadTree& amp;联盟

时间:2009-11-20 13:29:03

标签: c++ debugging unions quadtree

我有以下类似四叉树的结构,其中每个单元格可以是内部节点或叶子。 如果是叶子,它可以存储颜色。 如果它是一个内部节点,它存储指向四个子节点的指针(可以是叶子节点或内部节点):

class RenderBucketCell{
public:
    RenderBucketCell();
    RenderBucketCell(float R, float G, float B, float A, unsigned short X, unsigned short Y);
    ~RenderBucketCell();

    void split();

    void collapse();

    bool isLeaf;
    RenderBucketCell* neighbours[8];
    unsigned short x;
    unsigned short y;
    union{
        struct{
            float r;
            float g;
            float b;
            float a;
        };
        struct{
            RenderBucketCell* children[4];
        };
    };
};

如果单元格是内部节点,则不需要存储颜色。如果它是一片叶子,那么它不需要存储指向孩子的指针。因此颜色和孩子应该共享相同的记忆(联合)

有一个函数split(),它将一个叶子转换为一个内部节点,并为当前单元格具有相同颜色的子(叶子)创建:

void RenderBucketCell::split(){
isLeaf=false;
float rt = r;//make backups of the values before setting the children (union)
float gt = g;
float bt = b;
float at = a;
unsigned short xt2 = x*2;
unsigned short yt2 = y*2;
children[0] = new RenderBucketCell(rt,gt,bt,at, xt2, yt2);
children[1] = new RenderBucketCell(rt,gt,bt,at, xt2+1, yt2);
children[2] = new RenderBucketCell(rt,gt,bt,at, xt2, yt2+1);
children[3] = new RenderBucketCell(rt,gt,bt,at, xt2+1, yt2+1);
}

现在我正在调试函数split()。我在线上设置了一个调试点

children[0] = new RenderBucketCell(rt,gt,bt,at, xt2, yt2);

所以现在: 调试器在此行停止,我观察成员值。我执行一个程序步骤,以便执行该行(指令光标现在在下一行)。执行该行后,子项[0]的指针值仍然相同!相反,子项[2]的指针值已经改变(连同浮点值b)

有人可以解释我这种行为吗?我做错了什么?

谢谢!

4 个答案:

答案 0 :(得分:1)

你正在使用可以在你的联盟中称为“匿名结构”的东西。我不相信这些是C ++标准的一部分,虽然我已经读过一些编译器支持它们。在所有情况下,我都会清除这些并使用以下内容:

union{
        struct {
                float r;
                float g;
                float b;
                float a;
        } color;
        struct {
                RenderBucketCell* children[4];
        } subnode;
};

您的代码会更加冗长,因为您必须引用renderBucketCell.color.r而不是renderBucketCell.r,但它可以解决您的问题。

答案 1 :(得分:0)

这很可能是使用联合的问题。 children [2]是编译器为union提供的第一个未分配的内存位置(假设有4个字节的浮点数和8个字节的指针)。我不确定为什么会这样,但这样的问题是工会不可取的结构的主要原因之一。

答案 2 :(得分:0)

我通过给节点四个无符号长整数来解决你的问题(一个节点可以有指针或数据)。当节点是子节点时,那些无符号长整数将转换为浮点数。当它是父节点时,它们存储子节点的地址。

但是,您必须绝对确定要使用此优化,因为它会成为调试的噩梦。

答案 3 :(得分:0)

子元素[0]的值相同并不是那么令人惊讶,因为每次运行程序时内存可能会以非常类似的方式进行分区,即子节点[0]中的内存值将仍然在上一次运行中,“operator new”可能只是检索上次使用的内存。那是我对那里发生的事情的猜测。

至于儿童[2],我并不完全确定。我唯一能想到的就是构造函数。