2010-12-31 13 views
10

Come si avviano manualmente i valori nell'array su heap? Se la matrice è variabile locale (in pila), può essere fatto modo molto elegante e veloce, così:Inizializzazione dell'array su heap

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

Sfortunatamente, codice seguente

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

emette un errore compilando

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

Devo usare il ciclo, o il modo non molto elegante come questo?

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

dall'aspetto dell'esempio, si desidera riempire gli elementi dell'array 0 .. N, con i valori 1 .. N + 1. Un ciclo for lo farebbe bene. Qual è il tuo intento reale? – EvilTeach

risposta

3

Questo è interessante: Pushing an array into a vector

Tuttavia, se questo non lo fanno per provare la seguente:

#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]); 
+0

Hai fatto un errore, dovrebbe essere 'std :: copy (stack_array, stack_array + 5, & array [0]);' – qed

+0

VLA (array di lunghezza variabile) non fa parte dello standard C++ –

+0

VLA in C++ quindi -1 – cat

3

È possibile definire matrice costante, come myConstArray [] = {1, 2, 3} e fare memcpy dopo new int [3].

+5

più in generale, utilizzare std :: copy per copiare gli oggetti anziché i pattern di bit. –

+0

Sfortunatamente questo è inefficiente nel migliore dei casi, e impossibile nel peggiore dei casi (se il tipo è una classe senza copia/assegnazione). – Yttrill

+0

Con tipo che è una classe senza copia/assegnazione, sarebbe impossibile utilizzare l'array costante. –

2

{1,2,3} è una sintassi molto limitata, specifica dell'inizializzazione della struttura del POD (apparentemente anche l'array in stile C era considerato uno). L'unica cosa che puoi fare è come int x[] = {1,2,3}; o int x[3] = {1,2,3};, ma non puoi né fare int x[3]; x={1,2,3}; né usare {1,2,3} in nessun altro posto.

Se stai facendo C++, è preferibile utilizzare qualcosa come std :: vector invece di array in stile C, poiché sono considerati pericolosi - ad esempio non puoi conoscere la loro dimensione e devi eliminarli con un delete[] , non un normale delete. Con std :: vector avrai comunque lo stesso problema di inizializzazione. Se ho usato molto questa inizializzazione, probabilmente creerei una macro che assegna a una variabile locale fittizia e quindi copio la memoria nella destinazione.

EDIT: Si potrebbe anche fare in questo modo (std :: vector ancora preferibile):

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

ma poi dovrete ignorare la funzione con diverso numero di argomenti, o utilizzare va_arg che è , di nuovo, non sicuro.

EDIT2: La mia risposta è valida solo per C++ 03, come altre persone hanno menzionato C++ 0x ha alcuni miglioramenti a questo.

0

C++ 0x serie ha definito il tipo speciale initializer_list e la sintassi speciale per questo (tipo di espressione {1, 2, 3} è std::initializer_list<int>). std::vector e std::array hanno costruttori da esso, quindi è possibile scrivere vector<int> v = {1, 2, 3}.

Non c'è una buona soluzione in C++ 98/C++ 03.

0

Se si desidera una risposta generale che funziona per tutti i tipi, allora ciò che si fa è:

  1. malloc() o l'operatore new() per creare un array di archiviazione Non inizializzato della lunghezza giusta , calcolato da nelts * sizeof (T)

  2. Creare un array costituito dall'argomento di un costruttore per ciascun elemento.

  3. Applicare il costruttore nel modulo di posizionamento a ciascun elemento utilizzando l'argomento corrispondente.

Questo funziona solo se lo stesso costruttore farà per ogni elemento. In caso contrario, avrete bisogno di una struttura dati e di un algoritmo più complicati per scegliere il costruttore giusto per ciascun elemento.

Un caso speciale di questo è di utilizzare un array di elementi reali e utilizzare il costruttore di copie, e un caso speciale di questo è quando il tipo è un POD e si può semplicemente usare memcpy per costruire il lotto in una volta.

Se il costruttore accetta due argomenti, sarà necessario scrivere una procedura di iniziatore (wrapper). Ad esempio:

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

e utilizzare quello invece di solo nuovo (p).