Object array initialization without default constructor Object array initialization without default constructor arrays arrays

Object array initialization without default constructor


You can use placement-new like this:

class Car{    int _no;public:    Car(int no) : _no(no)    {    }};int main(){    void *raw_memory = operator new[](NUM_CARS * sizeof(Car));    Car *ptr = static_cast<Car *>(raw_memory);    for (int i = 0; i < NUM_CARS; ++i) {        new(&ptr[i]) Car(i);    }    // destruct in inverse order        for (int i = NUM_CARS - 1; i >= 0; --i) {        ptr[i].~Car();    }    operator delete[](raw_memory);    return 0;}

Reference from More Effective C++ - Scott Meyers:
Item 4 - Avoid gratuitous default constructors


Nope.

But lo! If you use std::vector<Car>, like you should be (never ever use new[]), then you can specify exactly how elements should be constructed*.

*Well sort of. You can specify the value of which to make copies of.


Like this:

#include <iostream>#include <vector>class Car{private:    Car(); // if you don't use it, you can just declare it to make it private    int _no;public:    Car(int no) :    _no(no)    {        // use an initialization list to initialize members,        // not the constructor body to assign them    }    void printNo()    {        // use whitespace, itmakesthingseasiertoread        std::cout << _no << std::endl;    }};int main(){    int userInput = 10;    // first method: userInput copies of Car(5)    std::vector<Car> mycars(userInput, Car(5));     // second method:    std::vector<Car> mycars; // empty    mycars.reserve(userInput); // optional: reserve the memory upfront    for (int i = 0; i < userInput; ++i)        mycars.push_back(Car(i)); // ith element is a copy of this    // return 0 is implicit on main's with no return statement,    // useful for snippets and short code samples} 

With the additional function:

void printCarNumbers(Car *cars, int length){    for(int i = 0; i < length; i++) // whitespace! :)         std::cout << cars[i].printNo();}int main(){    // ...    printCarNumbers(&mycars[0], mycars.size());} 

Note printCarNumbers really should be designed differently, to accept two iterators denoting a range.


You can create an array of pointers.

Car** mycars = new Car*[userInput];for (int i=0; i<userInput; i++){    mycars[i] = new Car(...);}...for (int i=0; i<userInput; i++){    delete mycars[i];}delete [] mycars;

or

Car() constructor does not need to be public. Add a static method to your class that builds an array:

static Car* makeArray(int length){    return new Car[length];}