2015-06-05 44 views
6

Mentre posso scriverePerché è richiesta la dimensione di un array assegnato all'heap con inizializzazione dell'elenco inizializzatore?

int n[] {1, 2, 3}; 

non posso scrivere

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

che dovrebbe essere

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

Qual è la ragione di questo?

+0

Intendevi 'int n [] = {1, 2, 3};'? –

+0

Puoi sempre fare [questo] (http://ideone.com/pq7Ytf), quindi chi vuole allocare l'array usando 'new'. Forse non sembra ragionevole giustificare il motivo per cui il codice di cui sopra non è permesso. –

+4

Vedere [CWG 1469] (http://open-std.org/JTC1/SC22/WG21/docs/cwg_closed.html#1469) – dyp

risposta

0

Ricordare che new in realtà è un operatore in C++.

Ciò è dovuto al modo in cui viene definito il nuovo operatore; cioè ha bisogno della dimensione della memoria richiesta come parametro di input esplicitamente. Quindi, non sarebbe dedotto dal conteggio dei membri dell'elenco inizializzatore.

+0

Abbiamo supporto per cose divertenti come 'new auto (5)'. Mentre 'new' è un operatore, non è ancora un operatore in cui è possibile sostituire l'intera semantica sovraccaricandola. In effetti, è possibile solo sovraccaricare/sostituire le funzioni di allocazione e deallocazione chiamate dall'operatore "incorporato" new (la nuova espressione). – dyp

+0

Non ho detto nulla di sovraccarico. Sto dicendo esattamente che 5 dovrebbe essere lì quando crei una nuova auto (5) a causa di "nuovo". Questo è tutto. –

+0

Mi spiace, ma potrei aver frainteso la tua risposta. Stai dicendo che non funziona perché non è specificato che funzioni attualmente (il codice OP è illegale nell'attuale C++)? O che non funziona perché c'è una ragione fondamentale per cui non può (anche teoricamente) funzionare? – dyp

-1

Per capire questo è necessario capire come funziona il nuovo operatore. Nuovo restituisce un puntatore all'inizio del nuovo blocco di memoria allocato. quindi quando diciamo

int* p = new int; 

stiamo allocando memoria per contenere un singolo elemento. Ma quando diciamo

int* foo = new [3]; 

stiamo assegnazione di un blocco di memoria per elementi di tipo int, dove "3" è il numero di blocco di memoria per il tipo intero. Quindi questo dice al compilatore che assegna memoria per 3 numeri interi. Quando facciamo questo

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

stiamo chiedendo al compilatore di allocare 3 posizione di memoria che memorizza il valore di tipo intero. Allo stesso tempo, assegniamo anche valori a tali posizioni di memoria.

Ora, se facciamo questo

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

non stiamo dicendo che il compilatore quantità di memoria da allocare, ma allo stesso tempo stiamo cercando di assegnare alla posizione 3 di memoria, ma non abbiamo stanziato più di tanto la memoria . In questo caso il compilatore assegna solo 1 blocco di memoria. Quindi il primo valore viene assegnato. Ciò causerà un errore di runtime.

Ora ciò che è strano è che, se l'è consentito al di sotto e il compilatore è abbastanza intelligente per assegnare 3 valori

int n[] = {1, 2, 3} 

perché non in questo caso

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

Credo che questo sia il problema a causa di come è progettato il nuovo operatore. Probabilmente si può provare a sovraccaricare il nuovo operatore e aggirare questo problema.

Spero che questo aiuti.

EDIT: Ho provato un codice fittizio in VS. Sembra che se lo fai

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

è un incidente.Ma quando lo fai,

int* p = new int []{1} 

questo perfettamente bene. Ciò dimostra che il compilatore lo sta interpretando come un comando per allocare solo un blocco di memoria.

+3

* "non stiamo dicendo al compilatore quanta memoria allocare" * Il compilatore può vedere che ci sono tre inizializzatori, proprio come nel caso di "int n [] = {1,2,3}' che menzioni. * "In questo caso il compilatore assegna solo 1 blocco di memoria" * No, questo è solo illegale (vietato tramite la grammatica della lingua). Se MSVC lo accetta, è un'estensione o un bug. – dyp