Инициализация массива на куче

Как вручную инициировать значения в массиве в куче? Если массив является локальной переменной (в стеке), его можно сделать очень элегантным и простым способом, например:

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

К сожалению, следующий код

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

выводит ошибку, компилируя

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

Нужно ли мне использовать цикл, или не очень-элегантный, как это?

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

Ответ 1

Это интересно: Нажатие массива в вектор

Однако, если это не делает это для вас, попробуйте следующее:

#include <algorithm>
...


const int length = 32;

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

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

Ответ 2

Вы можете определить постоянный массив, например myConstArray [] = {1, 2, 3}, и выполнить memcpy после нового int [3].

Ответ 3

{1,2,3} - очень ограниченный синтаксис, специфичный для инициализации структуры POD (по-видимому, также был рассмотрен массив C-style). Единственное, что вы можете сделать, это как int x[] = {1,2,3}; или int x[3] = {1,2,3};, но вы не можете выполнять ни int x[3]; x={1,2,3};, ни использовать {1,2,3} в любом другом месте.

Если вы делаете С++, предпочтительнее использовать что-то вроде std::vector вместо массивов в стиле C, поскольку они считаются опасными - например, вы не можете знать их размер и должны удалить их с помощью delete[], а не нормальный delete. Однако при использовании std::vector у вас все еще будет одна и та же проблема инициализации. Если бы я много использовал такую ​​инициализацию, я бы, скорее всего, создал макрос, назначающий фиктивную локальную переменную, а затем копирование памяти в пункт назначения.

EDIT: вы также можете сделать это (std::vector еще предпочтительнее):

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

но тогда вам придется переопределить функцию с различным количеством аргументов или использовать va_arg, который также является небезопасным.

EDIT2: Мой ответ действителен только для С++ 03, так как другие люди упомянули, что С++ 0x имеет некоторые улучшения.

Ответ 4

Стандарт С++ 0x имеет специальный тип, называемый initializer_list, и специальный синтаксис для него (тип выражения {1, 2, 3} - std::initializer_list<int>). std::vector и std::array имеют конструкторы, поэтому вы можете написать vector<int> v = {1, 2, 3}.

В С++ 98/С++ 03 нет хорошего решения.

Ответ 5

Если вам нужен общий ответ, который работает для всех типов, то что вы делаете:

  • malloc() или operator new() для создания массива неинициализированного хранения правильной длины, рассчитанного nelts * sizeof (T)

  • Сделать массив, состоящий из аргумента для конструктора для каждого элемента.

  • Применить конструктор в форме размещения к каждому элементу, используя соответствующий аргумент.

Это работает только в том случае, если для каждого элемента будет выполняться один и тот же конструктор. Если нет, вам понадобится более сложная структура данных и алгоритм для выбора правильного конструктора для каждого элемента.

Частным случаем является использование массива фактических элементов и использование конструктора копирования, а особый случай - когда тип является POD, и вы можете просто использовать memcpy для сборки партии сразу.

Если конструктор принимает два аргумента, вам нужно будет написать процедуру инициатора (обертку). Например:

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); }

и используйте это вместо просто нового (p).