【问题标题】:problem with quadTree & union四叉树和联合的问题
【发布时间】:2009-11-20 13:29:03
【问题描述】:

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

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)

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

谢谢!

【问题讨论】:

  • RenderBucketCell 构造函数是否有可能调用split()? (我假设不是,但最好检查一下。)
  • 嘿,Dave 不 - 构造函数只是为字段 r、g、b、a、isLeaf、neighbours[8]、x 和 y 设置默认值
  • 此时,有必要询问您正在使用什么编译器和调试器,因为您的代码看起来不错。 split() 是在与 RenderBucketCell 的其余部分不同的文件中实现的吗?似乎它对整数/指针的大小或对齐使用了不同的设置。

标签: c++ debugging unions quadtree


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

        【解决方案4】:

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-04-08
          • 2017-08-09
          • 2011-10-21
          • 2012-11-09
          • 1970-01-01
          • 2011-10-26
          • 2018-01-11
          相关资源
          最近更新 更多