2

質問にstackoverflowを使用するのはこれが初めてです。以前にいくつかの回答を読んだことがあり、場合によっては役に立ちました。探している特定の回答が見つからないので、登録すると思いました。最近、私はそれができるかどうかを確認するために、数百から数千の粒子を吐き出す非常に単純な粒子システムを作成しました。これを開始する前に、テンプレートを使用する単純なリンクリストを作成しましたそう選びます。

最近、私の同僚がパーティクル システムで遊んでいるのを見た後、私はそれを改善するために自分のプロジェクトを再検討することにしました。リンク リストを使用するという考えを明らかに捨て、代わりに配列と 3 つのポインタを使用してパーティクルを管理する小さな例を見つけるために、インターネットを精査しました。概念の大部分は理解できますが、何らかの理由で 1 つのことがわかりません。

 /// the first particle in the linked list
    Particle* start=0;

/// the next free particle
Particle* last=0;

/// the end of the memory allocation
Particle* end=0;

void SetSize(unsigned int size) {

    // delete any previous data
    delete [] start;

    // allocate new particles 
    last = start = new Particle[size];

    // set end
    end = start+size;
}

void AddOne() {

    // if we have no more memory left for any particles, ignore
    // the request to creat one.
    if (!IsFull()) {
        *last = Particle();
        ++last;
    }

}

void EraseOne(Particle* p) {

    if (!IsEmpty()) {
        *p = *(--last);
    }

}

上記のコードから私が理解していることから、3 つのポインターは配列内の要素への単純なポインターとして機能します。開始ポインタはゼロのままで、終了ポインタは配列の最後に残りますが、最後は開始ポインタと同じ位置から開始し、最後に到達するまでインデックス カウンタのように移動します。

私が確信していないのは消去ビットです。上記のコードから、「p」は最後のポインターが指している粒子ではなく、最後の前の粒子になっていると思います。残念ながら、前の1つは完全に生きている粒子であるため、なぜこのように行われるのかわかりませんが、これは同じ粒子の2つのインスタンスを作成しませんか?

4

1 に答える 1

1

まず最初に、半分焼き付けた手動実装を試すのではなく、標準のコンティナーを使用する必要があります。次に、コードの解釈について説明します。

コードは一般的なパターンを示しています。基本的に、3つのポインタを使用します。1つは割り当てられたメモリの先頭(と同等begin())、1つは最後の要素を超えたポインタ(と同等end()、3つ目のポインタは最後に割り当てられたブロックを超えたもの)(オーバーフローを回避するため)です。

それを念頭に置いて、関数の解釈は難しくありません。特に、AddOne(バッファーを拡張しない場合と同様push_backですが)最初の要素を最後から更新し、ポインターをインクリメントして、新しい最後の要素を超えた要素を参照します。

現在、EraseOne基本的に逆の操作を実行します。最初にポインタをデクリメントし(したがって、前の最後の要素が有効な範囲外になります)、次にその要素をコピーします(ポインタが最後を超えた要素を参照していることに注意してください)。

于 2012-02-16T02:25:17.747 に答える