rimosso il tag C, visto che quello era causando qualche confusione (che non avrebbe dovuto essere lì per cominciare;. Scusa per gli eventuali disagi ci C rispondere come sempre il benvenuto se :)Creazione di oggetti di dimensioni dinamicamente
In alcune cose che ho fatto, ho trovato la necessità di creare oggetti che hanno una dimensione dinamica e una dimensione statica, dove la parte statica è i membri di base dell'oggetto, la parte dinamica è comunque un array/buffer aggiunto direttamente sulla classe, mantenendo la memoria contigua, diminuendo così la quantità di allocazioni necessarie (questi sono oggetti non riallocabili) e riducendo la frammentazione (anche se come un lato negativo, potrebbe essere più difficile trovare un blocco di dimensioni abbastanza grandi, tuttavia questo è molto più raro - se dovrebbe anche o ccur affatto - che frammentare l'heap. Questo è utile anche su dispositivi embedded in cui la memoria è di livello premium (tuttavia non faccio nulla per i dispositivi embedded al momento), e cose come std :: string devono essere evitate, o non possono essere usate come nel caso di sindacati banali.
In generale il modo in cui mi piacerebbe andare su questo sarebbe quello di (ab) usare malloc (std :: string non viene utilizzato di proposito, e per vari motivi):
struct TextCache
{
uint_32 fFlags;
uint_16 nXpos;
uint_16 nYpos;
TextCache* pNext;
char pBuffer[0];
};
TextCache* pCache = (TextCache*)malloc(sizeof(TextCache) + (sizeof(char) * nLength));
Questo però non lo fa siedo troppo bene con me, come in primo luogo desidero fare questo ambiente utilizzando nuova, e quindi in C++, e in secondo luogo, sembra orribile: P
passo così la prossima era una variante su modelli C++:
template <const size_t nSize> struct TextCache
{
uint_32 fFlags;
uint_16 nXpos;
uint_16 nYpos;
TextCache<nSize>* pNext;
char pBuffer[nSize];
};
Questo h ha owever il problema che memorizza un puntatore a un oggetto di dimensioni variabile diventa 'impossibile', così poi il successivo lavoro intorno:
class DynamicObject {};
template <const size_t nSize> struct TextCache : DynamicObject {...};
Questo tuttavia richiede ancora colata, e avendo puntatori a DynamicObject dappertutto diventa ambiguo quando più che un oggetto di dimensioni dinamiche deriva da esso (sembra anche orribile e può soffrire di un bug che costringe le classi vuote ad avere ancora una dimensione, anche se questo è probabilmente un bug arcaico, estinto ...).
poi c'è stato questo:
class DynamicObject
{
void* operator new(size_t nSize, size_t nLength)
{
return malloc(nSize + nLength);
}
};
struct TextCache : DynamicObject {...};
che sembra molto meglio, ma potrebbero interferire con gli oggetti che hanno già sovraccarichi di nuovo (che potrebbe anche influenzare nuova collocazione ...).
Infine mi si avvicinò con nuova collocazione abusando:
inline TextCache* CreateTextCache(size_t nLength)
{
char* pNew = new char[sizeof(TextCache) + nLength];
return new(pNew) TextCache;
}
Questo però è probabilmente la peggiore idea finora, per un bel paio di motivi.
Quindi ci sono modi migliori per farlo? o sarebbe una delle versioni precedenti essere migliore, o almeno migliorabile? Sta addirittura prendendo in considerazione la pratica di programmazione sicura e/o cattiva?
come ho detto sopra, sto cercando di evitare doppie assegnazioni, perché questo non dovrebbe aver bisogno di 2 assegnazioni, e causare questo rende la scrittura (serializzazione) queste cose ai file molto più facile. L'unica eccezione al requisito di doppia allocazione che ho è quando il suo overhead è praticamente zero. l'unica causa in cui mi sono imbattuto è dove alloco sequenzialmente la memoria da un buffer fisso (using this system, che mi è venuta in mente), ma è anche un'eccezione speciale per evitare la copia superfluo.
C'è qualche motivo per cui non si desidera utilizzare STL? –
@Kornel: forse a causa del tag 'C' - ma gli esempi suggeriscono che forse il tag C è superfluo (anche se la mia risposta si concentra su C). –
@Kornel: alcune delle cose che ho in mente non possono usare STL, a causa di esse a) usando allocatori che non sono amichevoli con STL, o b) sono allocatori stessi, e l'uso di STL potrebbe sconfiggere scopo completo della loro esistenza. – Necrolis