Initialization of array on heap

2020-07-03 06:32发布

问题:

How do i manually initiate values in array on heap? If the array is local variable (in stack), it can be done very elegant and easy way, like this:

int myArray[3] = {1,2,3};

Unfortunately, following code

int * myArray = new int[3];
myArray = {1,2,3};

outputs an error by compiling

error: expected primary-expression before ‘{’ token
error: expected `;' before ‘{’ token

Do i have to use cycle, or not-so-much-elegant way like this?

myArray[0] = 1;
myArray[1] = 2;
myArray[2] = 3;

回答1:

This is interesting: Pushing an array into a vector

However, if that doesn't do it for you try the following:

#include <algorithm>
...


const int length = 32;

int stack_array[length] = { 0 ,32, 54, ... }
int* array = new int[length];

std::copy(stack_array, stack_array + length, &array[0]);


回答2:

You can define constant array, like myConstArray[] = {1, 2, 3} and do memcpy after new int[3].



回答3:

{1,2,3} is a very limited syntax, specific to POD structure initialization (apparently C-style array was considered one too). The only thing you can do is like int x[] = {1,2,3}; or int x[3] = {1,2,3};, but you can't do neither int x[3]; x={1,2,3}; nor use {1,2,3} in any other place.

If you are doing C++, it is preferable to use something like std::vector instead of C-style arrays, as they are considered dangerous - for example you can't know their size and must delete them with a delete[], not a normal delete. With std::vector you will still have the same initialization problem, though. If I used such initialization a lot, I would most probably create a macro assigning to a dummy local variable and then copying memory to the destination.

EDIT: You could also do it like this (std::vector still preferable):

int* NewArray(int v1, int v2, int v3) { /* allocate and initialize */ }
int* p = NewArray(1,2,3);

but then you'll have to override the function with different number of arguments, or use va_arg which is, again, unsafe.

EDIT2: My answer is only valid for C++03, as other people mentioned C++0x has some improvements to this.



回答4:

C++0x standard has the special type called initializer_list and the special syntax for it (type of expression {1, 2, 3} is std::initializer_list<int>). std::vector and std::array have constructors from it, so you can write vector<int> v = {1, 2, 3}.

There is no good solution in C++98/C++03.



回答5:

If you want a general answer that works for all types, then what you do is:

  1. malloc() or operator new() to create an array of uninitialised storage of the right length, calculated by nelts * sizeof(T)

  2. Make an array consisting of the argument for a constructor for each element.

  3. Apply the constructor in placement form to each element using the corresponding argument.

This only works if the same constructor will do for every element. If not, you will need a more complicated data structure and algorithm to choose the right constructor for each element.

A special case of this is to use an array of the actual elements and use the copy constructor, and a special case of that is when the type is a POD and you can just use memcpy to construct the lot at once.

If the constructor takes two arguments, you will need to write an initiator procedure (wrapper). For example:

pair<double> init_data[] = {make_pair(1.0,0.0), make_pair(3.0,4.0)};
void init(void *p, pair<double> d) { new (p) complex(d.first, d.second); }

and use that instead of just new(p).



回答6:

This can be accomplished today with the following syntax:

int * myHeapArray = new int [3] {1, 2, 3};

Notice you have to match the size of the structure you're allocating with the size of the initializer-list.

Since I'm replying to a question posted years ago, it is worth mentioning that modern C++ discourages the use of new, delete and native (or naked) pointers. The use of handlers such as std::unique_ptr and std::shared_ptr are favored instead, since they automatically release the memory they own (check RAII idiom).

In this particular case, std::vector would provide all such features: heap-allocated data, use of initializer-list (like {1, 2, 3}), handlers and move semantics among other features.

For stack-allocated arrays you can consider std::array, should you need them.