How do I declare an array of objects whose class has no default constructor?

If a class has only one constructor with one parameter, how to declare an array? I know that vector is recommended in this case. For example, if I have a class

class Foo{

public:
Foo(int i) {}

}

How to declare an array or a vector which contains 10000 Foo objects?


Solution 1:

For an array you would have to provide an initializer for each element of the array at the point where you define the array.

For a vector you can provide an instance to copy for each member of the vector.

e.g.

std::vector<Foo> thousand_foos(1000, Foo(42));

Solution 2:

Actually, you can do it as long you use an initialization list, like

Foo foos[4] = { Foo(0),Foo(1),Foo(2),Foo(3) };

however with 10000 objects this is absolutely impractical. I'm not even sure if you were crazy enough to try if the compiler would accept an initialization list this big.

Solution 3:

sbi had the best answer for plain arrays, but didn't give an example. So...

You should use placement new:

char *place = new char [sizeof(Foo) * 10000];
Foo *fooArray = reinterpret_cast<Foo *>(place);
for (unsigned int i = 0; i < 10000; ++i) {
    new (fooArray + i) Foo(i); // Call non-default constructor
}

Keep in mind that when using placement new, you are responsible for calling the objects' destructors -- the compiler won't do it for you:

// In some cleanup code somewhere ...
for (unsigned int i = 0; i < 10000; ++i) {
    fooArray[i].~Foo();
}

// Don't forget to delete the "place"
delete [] reinterpret_cast<char *>(fooArray);

This is about the only time you ever see a legitimate explicit call to a destructor.

NOTE: The first version of this had a subtle bug when deleting the "place". It's important to cast the "place" back to the same type that was newed. In other words, fooArray must be cast back to char * when deleting it. See the comments below for an explanation.