2

i は次の四分木のような構造を持ち、各セルは内部ノードまたはリーフのいずれかになります。葉であれば、色を保存できます。内部ノードの場合は、4 つの子 (リーフまたは内部ノードのいずれか) へのポインターを格納します。

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] のポインタ値が (float 値 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 バイトのポインタを想定)。なぜそうなったのかはわかりませんが、このような問題は、労働組合が望ましい構造ではない主な理由の 1 つです。

于 2009-11-20T23:25:00.740 に答える
0

ノードに 4 つの unsigned long を与えることで、問題 (ノードはポインターまたはデータのいずれかを持つことができます) を解決しました。ノードが子ノードの場合、これらの unsigned long は float にキャストされます。親ノードの場合は、子ノードのアドレスを格納します。

ただし、デバッグが困難になるため、この最適化を使用する必要があることを完全に確認する必要があります。

于 2009-11-20T23:37:44.367 に答える
0

children[0] の値が同じであることはそれほど驚くべきことではありません。プログラムを実行するたびにメモリがおそらく非常に似た方法で分割されるためです。つまり、children[0] のメモリ内の値はまだ存在します。前回の実行から、「operator new」はおそらく前回使用されたメモリを取得するだけです。それがそこで何が起こっているかについての私の推測です。

子供[2]に関しては、完全にはわかりません。私が考えることができる唯一のことは、コンストラクターに関するものです。

于 2009-12-06T10:20:45.700 に答える