Search code examples
c++arraysvectorreferenceinstance

Adding a new instance of an array to a vector


This is a continuation of my previous question: Nested vector<float> and reference manipulation.

I got the loops and all working, but I'm trying to add new instances of arrays to a total vector.

Here's one example of what I mean:

array<float, 3> monster1 = { 10.5, 8.5, 1.0 };
// ...
vector<array<float, 3>*> pinkys = { &monster1};
// ...
void duplicateGhosts() {

    int count = 0; 
    int i = pinkys.size(); // this line and previous avoid overflow

    array<float, 3>& temp = monster1; // this gets the same data, but right now it's just a reference

    for (auto monster : pinkys) { // for each array of floats in the pinkys vector,
        if (count >= i)           // if in this instance of duplicateGhosts they've all been pushed back,
            break;                
        pinkys.push_back(&temp);  // this is where I want to push_back a new instance of an array
        count++;
    }
}

With the current code, instead of creating a new monster, it is adding a reference to the original monster1 and therefore affecting its behavior.


Solution

  • As mentioned in a comment you cannot insert elements to a container you are iterating with a range based for loop. That is because the range based for loop stops when it reaches pinkys.end() but that iterator gets invalidated once you call pinkys.push_back(). It is not clear why you are iterating pinkys in the first place. You aren't using monster (a copy of the elements in the vector) in the loop body.

    The whole purpose of the loop seems to be to have as many iterations as there are already elements in the container. For that you need not iterate elements of pinkys but you can do:

     auto old_size = pinkys.size();
     for (size_t i=0; i < old_size; ++i) {
          // add elements
     }
    

    Further, it is not clear why you are using a vector of pointers. Somebody has to own the monsters in the vector. If it isnt anybody else, it is the vector. And in that case you should use a std::vector<monster>. For shared ownership you should use std::shared_ptr. Never use owning raw pointers!

    Don't use a plain array for something that you can give a better name:

     struct monster {
          float hitpoints;  // or whatever it actually is.
          float attack;     // notice how this is much clearer
          float defense;    // than using an array?
     };
    

    With those modifications the method could look like this:

    void duplicateGhosts() {
         auto old_size = pinkys.size();
         for (size_t i=0; i < old_size; ++i) {
             pinkys.push_back( pinkys[i] );
         }       
    }
    

    From the name of the method I assumed you want to duplciate the vectors elements. If you want to just add the same monster as many times as there were elements before, that is

    void duplicateGhosts() {
         auto old_size = pinkys.size();
         for (size_t i=0; i < old_size; ++i) {
             pinkys.push_back( monster{} );
         }       
    }