As many other questions and answers already stated, there is no syntax in C++ which allows you to declare and fill a dynamic-sized array with non-default constructible objects.
Obj* array = new Obj[size];
Here, if Obj
has a default constructor, it will be used to fill array
with size
default-constructed instances of Obj
, which is a problem.
The most recurrent answers to this question mention vectors (here), or the mechanism used by vectors, the placement new (here). However, the former is not an option in my case, and I would like to avoid the latter because it looks plain dirty and messy to me (being used by the STL perhaps makes it a nice way to do things, but it really does look messy).
Edit: why vectors are not an option: This project is a challenge I want to test myself against, and I want to get my hands in the dirt as much as I can. If not using vectors means using placement news as stated below, then that is what I will do.
I do realise that I complained about placement news being messy, and I also do realise that getting hands in the dirt does imply having to handle such mess.
Another recurrent answer is to use the curly braces to fill the array with non-default constructed objects:
Obj* array = new Obj[2] {Obj(foo), Obj(bar)};
That makes it a half-dynamic-sized array, if I may say. Being allocated on the heap makes it not static, but the size has to be a compile-time constant, so I would not consider it fully dynamic (or at least not as much as I want it to be).
The most obvious solution to me would be to declare the array as above, let it be filled with junk, default-constructed Objects, and then re-fill it up with the correct objects, as follows:
Obj* array = new Obj[size];
for (int i = 0; i < size; i++)
{
array[i] = Obj(whatever);
}
However, performance is a great deal in my program, and I am quite concerned about the performance impact of such methods. If size
is 10000, the array would be filled with 10000 junk objects, which could be very time-expensive. Then, the cost of the replacement afterwards could be even worse (while still possible to minimise with efficient use of the copy-and-swap idiom), and that too is a concern.
Instead, I was thinking of using a double malloc
.
Obj** array = malloc(sizeof(Obj*) * size);
for (int i = 0; i < size; i++)
{
array[i] = malloc(sizeof(Obj));
array[i] = new Obj(whatever);
}
//...
for (int i = 0; i < size; i++)
{
delete array[i];
free(array[i]);
}
free(array);
But that looks totally not cache-friendly. And it just does not feel right having a pair of malloc
(having only one already feels not okay).
So here is my question: is there a nice and clean way that allows you to allocate uninitialised memory, and then fill it with custom-constructed objects, that does not degrade performance?
Edit: my real question is: are there other ways than the ones I mentioned above?
(P.S.: I know that "uninitialised memory" does not go well with RAII, and thus does not go well with "nice and clean")
vector
not an option for you? And what about a custom collection class with similar properties to a vector? – CodesInChaos Jan 8 at 12:02