Initializer list for dynamic arrays?

31,689

Solution 1

No, you cannot do that.

I think C++ doesn't allow this because allowing such thing doesn't add any nice-to-have feature to the language. In other words, what would be the point of dynamic array if you use a static initializer to initialize it?

The point of dynamic array is to create an array of size N which is known at runtime, depending on the actual need. That is, the code

int *p = new int[2]; 

makes less sense to me than the following:

int *p = new int[N]; //N is known at runtime

If that is so, then how can you provide the number of elements in the static initializer because N isn't known until runtime?

Lets assume that you're allowed to write this:

int *p = new int[2] {10,20}; //pretend this!

But what big advantage are you getting by writing this? Nothing. Its almost same as:

int a[] = {10,20};

The real advantage would be when you're allowed to write that for arrays of N elements. But then the problem is this:

 int *p = new int[N] {10,20, ... /*Oops, no idea how far we can go? N is not known!*/ };

Solution 2

At the time the OP posted this question, C++11 support may not have been very prevalent yet, which is why the accepted answer says this is not possible. However, initializing a dynamic array with an explicit initializer list should now be supported in all major C++ compilers.

The syntax new int[3] {1, 2, 3} was standardized in C++11. Quoting the new expression page on cppreference.com:

The object created by a new-expression is initialized according to the following rules:
...
If type is an array type, an array of objects is initialized:
...
If initializer is a brace-enclosed list of arguments, the array is aggregate-initialized. (since C++11)

So, given the OP's example, the following is perfectly legal when using C++11 or newer:

foo * foo_array = new foo[2] { nullptr, nullptr };

Note that by providing pointers in the initializer list, we're actually coaxing the compiler to apply the foo(void * ptr) constructor (rather than the default constructor), which was the desired behavior.

Solution 3

No, you will have to create the elements dynamically.

Alternatively, you can use a local array and copy its elements over those of the dynamically allocated array:

int main() {
   int _detail[] = { 1, 2 };
   int * ptr = new int[2];
   std::copy( _detail, _detail+(sizeof detail / sizeof *detail), ptr );
   delete [] ptr;
}

In the limited version of setting all elements to 0, you can use an extra pair of parenthesis in the new call:

int * ptr = new int[2]();  // will value initialize all elements

But you seem to be looking for a different thing.

Share:
31,689
ritter
Author by

ritter

Updated on June 20, 2020

Comments

  • ritter
    ritter about 4 years

    It is possible to give an initializer list to the definition of a static array. Example:

    int main()
    {
      int int_static[2] = {1,2};
    }
    

    Is a similar initializer list possible for a dynamic array?

    int main()
    {
      int* int_ptr = new int[2];
    }
    

    This is closer to what I am trying to do:

    struct foo
    {
      foo(){}
      foo(void * ptr): ptr_(ptr) {}
      void * ptr_;
    };
    
    int main()
    {
      foo* foo_ptr = new foo[10];
    }
    

    At initialization time not the default constructor should be called, but foo:foo(void*).

    The point of having a static initializer list for a dynamic array might come handy in the case of Just-In-Time compilation for accelerator cores which do have only a limited amount of stack available, but at the same time you construct your objects with a (accelerator compile time = host run time) static initializer list.

    I assume not (since this would require the compiler to generate additional code, namely to copy the values of the arguments to the heap location). I think c++0x supports some of this, but I cannot use it. Right now I could use such a construct. Maybe someone knows a trick..

    Best!

  • Oliver Charlesworth
    Oliver Charlesworth almost 13 years
    This isn't particularly clear. Could you give an illustrative example?
  • David Rodríguez - dribeas
    David Rodríguez - dribeas almost 13 years
    @Oli, I guess he refers to something similar to the solution that I suggest in my answer, just ignoring the gory details of the needed copy.
  • Lightness Races in Orbit
    Lightness Races in Orbit almost 13 years
    The punctuation in your first sentence was a little misleading; have "fixed". Rollback if you disagree.
  • ritter
    ritter almost 13 years
    I am looking exactly for a way to call the constructor of each element that is dynamically allocated (of course its not just an "int"). But its not the standard constructor that has to be called. It must take 1 arg and the lvalue for that argument is for each element different.
  • Mooing Duck
    Mooing Duck almost 13 years
    shouldn't _detail be an int*?
  • Cheers and hth. - Alf
    Cheers and hth. - Alf almost 13 years
    However, I seem to be "getting" this about SO that in order for answer to be grokked, it needs to be fleshed out with very detailed example, giving the man a fish. I generally don't think to do that because it's the thing to absolutely not do in order to help someone. Even though it is the thing to do in order to get upvotes.
  • David Rodríguez - dribeas
    David Rodríguez - dribeas almost 13 years
    Thanks to Tomalak and James for fixing the answer.
  • David Rodríguez - dribeas
    David Rodríguez - dribeas almost 13 years
    The next set of questions are about the actual requirements (that again, like most others, you have not provided): why does it have to be dynamically allocated? why can you not use std::vector? do you control both allocation an deallocation?
  • Mike Housky
    Mike Housky over 9 years
    For the record, "dynamic" does not mean "variable-length". It is indeed a "nice-to-have feature" to be able to create a new dynamic object and initialize it to known initial contents. That's precisely what constructors do for class and struct type objects.
  • holocronweaver
    holocronweaver almost 9 years
    To clarify, 'dynamic' in C++ means allocated on the heap instead of the stack. I use both memory stores extensively, so having initializer lists work for both would be extremely convenient. As is, in many cases when I want to create a array list on the heap I have to resort to objects (like std::vector) instead of plain arrays because, as @MikeHousky says, C++ only supports initializing objects on the heap at the moment, not arrays. No techincal or performance issue here - just a limitation of C++.