2009-11-20 82 views
2

我有以下類似四叉樹的結構,其中每個單元可以是內部節點或葉。 如果它是一片葉子,它可以存儲一種顏色。 如果它是一個內部節點,它存儲的指針到四個孩子(其可以是葉或內節點):quadTree與union的問題

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

調試點: 調試器停在這條線,我觀察membervalues。我做了一個程序步,這樣該行被執行(指令光標現在在下一行)。行被執行後,children [0]的pointervalue仍然是一樣的!相反,兒童[2]的指針值已經改變(與浮點值b一起)

有人可以解釋我這種行爲嗎?我究竟做錯了什麼?

謝謝!

+0

有沒有可能'RenderBucketCell'構造函數可能調用'split()'? (我認爲不是,但最好檢查一下。) – dave4420 2009-11-20 16:57:37

+0

哎Dave no - 構造函數只是爲字段r,g,b,a,isLeaf,neighbors設置默認值[8],x和y – Mat 2009-11-20 17:14:42

+0

此時,它是值得問一下你使用的編譯器和調試器,因爲你的代碼看起來不錯。 Split()是否在與RenderBucketCell的其餘部分分開的文件中實現?它似乎使用不同的整數/指針大小或對齊方式。 – Joh 2009-12-06 11:16:27

回答

0

這很可能是使用聯合的問題。 children [2]是編譯器給union的第一個未分配的內存位置(假設有4個字節的浮點數和8個字節的指針)。我不確定爲什麼會發生這種情況,但是像這樣的問題是工會不是可取的結構的主要原因之一。

0

我通過給節點四個unsigned long來解決你的問題(一個節點可以有指針或數據)。當節點是一個子節點時,那些無符號的long被轉換爲浮點數。當它是父節點時,它們存儲子節點的地址。

但是,您必須絕對確定要使用此優化,因爲它成爲調試的噩夢。

0

兒童[0]的值是相同的並不令人意外,因爲每次運行程序時內存可能會以非常相似的方式進行分區,即兒童內存中的值[0]仍然會在上一次運行中出現,「新操作員」很可能只是檢索上次使用的內存。這是我對那裏發生的事情的猜測。

至於兒童[2],我不完全確定。我能想到的唯一的東西就是構造函數。

1

您正在使用可以在聯合中稱爲「匿名結構」的東西。我不相信這些是C++標準的一部分,儘管我讀過一些編譯器支持它們。在任何情況下,我會留下清晰的這些和使用以下命令:

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

您的代碼將是稍微詳細,你必須參考renderBucketCell.color.r而不是renderBucketCell.r,但它可以解決您的問題。