Инициализация массива на куче
Как вручную инициировать значения в массиве в куче?
Если массив является локальной переменной (в стеке), его можно сделать очень элегантным и простым способом, например:
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).