Iterate an Object Array
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 &lt;stdlib.h&gt;

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 &lt; trainCount; ++i) {
        trains[i].numOfCars = 5;
        trains[i].init();
    }
    Serial.begin(9600);
}

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