3

I'm trying to create an array of objects and later iterate over it and do something with each object. My C++ skills just don't go far enough.

Here's what I have so far. I've tried to strip out all the meaningless code. Whats wrong is my tr object is not what I expect it to be. It's numOfCars property is 0 so I know I'm not accessing the train object that I expected.

#include <stdlib.h>

class Train {
    public:
        int numOfCars;
        void init();
        void move();
};

void Train::init() {
    //code intentionally removed
}

void Train::move() {
    //code intentionally removed
}

const int trainCount = 2;
Train train1;
Train train2;
Train trains[trainCount] {train1, train2};

void setup() {  
    Serial.begin(9600);
    train1.numOfCars = 5;
    train1.init();

    train2.numOfCars = 5;
    train2.init();
}

void loop() {
    for(int n = 0; n < trainCount; n++) {
        Train tr = trains[n];
        Serial.println(tr.numOfCars); //always prints 0
        tr.move();    
    }
}
5

You are not creating an array of references, you are creating the array from the objects; they are being copied. You can see that this by moving the line (and adding an equals)

Train trains[trainCount] = {train1, train2};

to the bottom of your setup method. However, that is beside the point, as you are not fully using the power of arrays. You needn't create separate objects everywhere, simply create an array of objects right off the bat with new[] and use them. Like this:

#include <stdlib.h>

class Train {
    public:
        int numOfCars;
        void init();
        void move();
};

void Train::init() {}
void Train::move() {}

const int trainCount = 2;
Train* trains = new Train[trainCount];

void setup() {
    // initialize trains
    for (int i = 0; i < trainCount; ++i) {
        trains[i].numOfCars = 5;
        trains[i].init();
    }
    Serial.begin(9600);
}

void loop() {
    for(int n = 0; n < trainCount; n++) {
        Serial.println(trains[n].numOfCars); //always prints 0
        trains[n].move();    
    }
}
  • Unless the Train constructor depends on other things being initialized first (in which case you would new in setup()), there is no point in using dynamic memory allocation: just declare Train trains[trainCount];. – Edgar Bonet Feb 19 '16 at 9:43
3

As uint128_t has already put it, your problem is that you are creating an array of copies. You should really avoid copying trains around, especially if you are going to put a significant amount of data in them. Instead, just create them once in the array, and then you can either invoke them as array members directly (e.g. trains[0].init();) or use references.

For example, if you initialize your trains like this:

const int trainCount = 2;
Train trains[trainCount];
Train &train1 = trains[0];
Train &train2 = trains[1];

Then the "real" trains live in the array, and train1 and train2 are references to them. The rest of your code should work fine unchanged. I would however suggest to avoid copying the trains in loop:

void loop() {
    for(int n = 0; n < trainCount; n++) {
        Train &tr = trains[n];        // notice the '&'!
        Serial.println(tr.numOfCars);
        tr.move();    
    }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.