我有以下类似四叉树的结构,其中每个单元格可以是内部节点或叶子。 如果是叶子,它可以存储颜色。 如果它是一个内部节点,它存储指向四个子节点的指针(可以是叶子节点或内部节点):
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)
有人可以解释我这种行为吗?我做错了什么?
谢谢!
答案 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],我并不完全确定。我唯一能想到的就是构造函数。