Ci sono due cose che devono essere chiarite qui.
Primo: l'assunto che malloc
mantenga la dimensione esatta richiesta.
Non proprio. malloc
si preoccupa solo di fornire un blocco sufficientemente grande. Sebbene, per ragioni di efficienza, probabilmente non sarà molto utile in generale, probabilmente ti darà un blocco di dimensioni "standard", ad esempio un blocco di byte 2^n
. Pertanto la dimensione reale (come in, il numero di oggetti effettivamente allocati) è effettivamente sconosciuta.
Secondo: il "qualcosa in più" necessaria
Infatti, le informazioni necessarie per un determinato oggetto per sapere se è parte di un array o non sarebbe semplicemente un po 'in più. Logicamente.
Per quanto riguarda l'implementazione, però: dove metteresti effettivamente quel pezzo?
La memoria allocata per l'oggetto stesso probabilmente non deve essere toccata, dopotutto l'oggetto lo sta utilizzando. Così ?
- su qualche piattaforma, questo potrebbe essere tenuto nel puntatore stesso (alcune piattaforme ignorano una porzione dei bit), ma questo non è portabile
- quindi richiederebbe memoria supplementare, almeno un byte, tranne che con problemi di allineamento potrebbe ammontare a 8 byte.
Dimostrazione:
(non convincente come notato da qc, vedi sotto)
// A plain array of doubles:
+-------+-------+-------
| 0 | 1 | 2
+-------+-------+-------
// A tentative to stash our extra bit
+-------++-------++-------++
| 0 || 1 || 2 ||
+-------++-------++-------++
// A correction since we introduced alignment issues
// Note: double's aligment is most probably its own size
+-------+-------+-------+-------+-------+-------
| 0 | bit | 1 | bit | 2 | bit
+-------+-------+-------+-------+-------+-------
Humpf!
EDIT
Pertanto, sulla maggior parte delle piattaforme (in cui l'indirizzo non importa), è necessario "estendere" ogni puntatore, e in realtà raddoppiare le loro dimensioni (problemi di allineamento).
È accettabile che tutti i puntatori siano due volte più grandi solo in modo da poter riporre quel bit in più? Per la maggior parte delle persone credo che sarebbe. Ma C++ non è progettato per la maggior parte delle persone, è progettato principalmente per le persone che hanno a cuore le prestazioni, che siano velocità o memoria, e come tale non è accettabile.
FINE EDIT
Allora, qual è la risposta corretta? La risposta corretta è che il recupero delle informazioni che il sistema di tipi ha perso è costoso. Purtroppo.
Stai chiedendo perché c'è 'delete []' invece di 'delete' che gestisce la deallocazione e la distruzione dell'array? –
È un piccolo costo, ma poi il guadagno per pagarlo è anche piccolo. –
A meno che lo standard non indichi esplicitamente che la dimensione dell'allocazione è memorizzata da qualche parte (ne dubito), non è sempre necessario memorizzare la dimensione allocata. Prendiamo il seguente esempio: 'int * p = new int;' L'unico modo per eliminarlo in un modo definito è chiamare delete su un 'int *'. Quindi la dimensione è implicitamente nota dal fatto che si sa che è un 'int'. (Nota, chiamando delete su un 'void *' è UB: http://stackoverflow.com/a/941959/239916). –