2

This is my first time using stackoverflow for a question, I have read a few answers previously which have helped me in some cases so I thought I'd register seeing as I can't find the specific answer I'm looking for. Recently I made a pretty simple particles system that spews out a couple 100 to 1000s of particles just to see if I could do it, before I even started this I made a simple Linked List which uses templates so I can use it in other programs if I so choose.

Recently, after seeing a colleague of mine playing about with a particle system he found I decided to revisit my project to improve upon it. I scoured the internet to find a little example which apparently ditches the idea of using a Linked List and instead uses and array and three pointers to manage the particles. I understand most of the concept but for some reason one thing escapes me.

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

}

From what I understand from the code above the three pointers act as simple pointers to the elements in the array. The start pointer remains at zero and the end pointer remains at the end of the array while last starts from the same position as the start pointer and moves along like an index counter until it gets to the end.

What I'm unsure of is the erasing bit, I assume from the code above that 'p' is becoming not the particle the last pointer is pointing to but the one before last. Unfortunately I have no idea why it is done this way as surely the one before last is a perfectly alive particle but wouldn't this make two instances of the same particle?

AstroCB
  • 12,337
  • 20
  • 57
  • 73
M Davies
  • 255
  • 1
  • 3
  • 11
  • Does this do anything that `std::vector` wouldn't do at least as well? – Jerry Coffin Feb 16 '12 at 01:46
  • @Bill could you elaborate a bit more? I know that no new particle is being created but from the implementation it seems like your just making the old particle the one before last which would mean you'd have two copies of last-1. Or am I getting the wrong end of the stick? – M Davies Feb 16 '12 at 01:55
  • @JerryCoffin It probably doesn't but I'm doing this just to know I can implement it really. Unfortunately on my course remaking the wheel is an important part of getting through the course so showing I can implement things without relying on existing libraries is a plus for any assignments I do. – M Davies Feb 16 '12 at 01:55
  • @Bill Ah, I may understand it now. If last is 20 and p is 3 p becomes last which is now 19 after it was decremented. Because last is now 19 then and end is 20 then the array is not full so you would overwrite 19 with the init call to effectively make new particle (in the terms of it's position, colour and life) last is then incremented along one step back to the end which is 20. Because p is 19 then the one that existed where last was can be made into a new one. Am I correct? – M Davies Feb 16 '12 at 02:22
  • @Bill and no, the update function cycles through all the particles changing their life and their position, if it comes to a particle that is at the end of its life that particle is passed into the EraseOne function. Not a null pointer. – M Davies Feb 16 '12 at 02:27
  • David's got a better explanation below. The last pointer points to one position after the last valid element, obviously not thinking correctly. – Bill Feb 16 '12 at 02:29

1 Answers1

1

The first thing is that you should use a standard continer rather than trying a half baked manual implementation. Now to the interpretation of the code:

The code shows a common pattern. Basically you use three pointers, one to the beginning of the allocated memory, (equivalent to begin()), a pointer one beyond the last element (equivalent to end() and a third pointer one beyond the last allocated block (to avoid overflowing.

With that in mind interpreting the functions is not hard. In particular, AddOne (similar to push_back but without growing the buffer) updates the first element beyond the end, and increments the pointer to refer to one beyond the new last element.

As of EraseOne basically performs the reverse operation: it first decrements the pointer (so now the previouslast element is outside of the valid range) and then copies that element (remember that the pointer refers to one beyond the end)

David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489
  • The previous last element is never outside of the valid range. But don't worry I believe I figured it out. Thanks for the help. – M Davies Feb 16 '12 at 02:51
  • It is outside of the range of elements that are *valid* in the container (semantically), which is not the same as saying outside of the allocated memory range. – David Rodríguez - dribeas Feb 16 '12 at 03:53