Инициализация массива в куче - PullRequest
12 голосов
/ 31 декабря 2010

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

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;

Ответы [ 5 ]

4 голосов
/ 31 декабря 2010

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

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

#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]);
3 голосов
/ 31 декабря 2010

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

2 голосов
/ 31 декабря 2010

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

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

РЕДАКТИРОВАТЬ: Вы также можете сделать это такпредпочтительно):

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

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

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

0 голосов
/ 31 декабря 2010

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

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

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

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

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

Особый случай этого - использование массива реальных элементов и использование конструктора копирования, а особый случай - когда тип является 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).

0 голосов
/ 31 декабря 2010
Стандарт

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...