2

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

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);

所以现在:调试器停在这一行,我观察成员值。我做了一个过程步骤,以便执行该行(指令光标现在位于下一行)。执行完这行代码之后,children[0] 的指针值还是一样的!相反,children[2] 的指针值发生了变化(连同浮点值 b)

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

谢谢!

4

4 回答 4

1

您在工会中使用了可以称为“匿名结构”的东西。我不相信这些是 C++ 标准的一部分,尽管我已经阅读了一些支持它们的编译器。在所有情况下,我都会避开这些并使用以下内容:

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

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

于 2009-12-09T18:07:41.560 回答
0

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

于 2009-11-20T23:25:00.740 回答
0

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

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

于 2009-11-20T23:37:44.367 回答
0

children[0] 的值相同并不奇怪,因为每次运行程序时内存可能会以非常相似的方式进行分区,即 children[0] 处的内存值仍然存在从上一次运行开始,“operator new”可能只会检索上次使用的内存。这是我对那里发生的事情的猜测。

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

于 2009-12-06T10:20:45.700 回答