C ++: STL o codice personalizzato per strutture dati?

1

Domanda generale riguardante l'STL. Ragazzi, pensate che l'STL debba essere usato per le strutture dati o vorreste creare un codice personalizzato? In quale scenario implementeresti il tuo codice per qualcosa che la libreria standard già fa? Quali sono i tuoi pensieri?

    
posta Dimos 12.07.2017 - 04:42
fonte

4 risposte

9

Non sono un esperto di STL, ma gli ingegneri del software IMO dovrebbero sempre preferire utilizzare le librerie mature per scrivere qualcosa di loro stessi a meno che non ci siano lacune nella libreria. Anche se la libreria non soddisfa completamente i requisiti, le librerie possono comunque essere estese e contribuire a soddisfare i requisiti. L'STL ha superato i test, è stato utilizzato per anni nei sistemi di produzione e i creatori hanno riflettuto molto sulle implementazioni, quindi dovrebbero essere abbastanza efficienti.

A meno che non ci sia un reale valore aggiunto per il tuo progetto, non penso che dovresti scrivere un codice personalizzato per le strutture di dati.

    
risposta data 12.07.2017 - 05:23
fonte
6

La risposta breve è usare STL se non del tutto ragionevole. Sviluppa il tuo codice solo se non hai un'alternativa ragionevole.

In alcuni casi, ci sono regole dure e veloci (di solito mal formulate, e scarsamente ragionate, ma forzate comunque) che tolgono completamente la decisione alle tue mani. Se è così, questo semplifica le cose.

Se ti è consentito giudicare in merito, cerca di usarlo bene. Inizia guardando gli obiettivi reali del tuo progetto, cosa deve fare, in quali circostanze ha bisogno di funzionare, e così via. Se stai scrivendo il codice per un microcontrollore che ha solo (diciamo) alcuni kilobyte di RAM, è molto probabile che STL sia non che andrà bene. Indipendentemente dal lavoro che potrebbe salvare, non funzionerà.

Al contrario, se stai sviluppando per un server moderno ragionevolmente alto che potrebbe facilmente avere centinaia di gigabyte di RAM (per non parlare di cose come la memoria di massa e così via), questo cambia completamente l'equazione; scrivere un nuovo codice per salvare un kilobyte (o anche un megabyte) di dimensioni eseguibili è probabile che sia un errore molto più spesso.

Vorrei anche notare che in alcuni casi, gli effetti cambiano leggermente nel tempo. Solo per esempio, molte delle prime implementazioni della STL sono andate a fare un po 'di tempo per risparmiare memoria. Una tecnica abbastanza comune era quella di dividere i contenitori in due parti: un "back-end" che funziona con (per esempio) i puntatori a void . Quindi avresti un "front end" minuscolo che ha appena fornito un'interfaccia sicura dal tipo: ad esempio, potrebbe lanciare un T * a void * quando lo memorizzi e lanciare void * in T * durante il recupero.

Ciò ha consentito di condividere praticamente tutto il codice per la raccolta (o qualsiasi altra cosa) tra tutte le istanze di tutti i tipi. L'istanziazione della raccolta su un nuovo tipo non ha praticamente aggiunto alcun nuovo codice (in molti casi i cast hanno appena modificato il modo in cui i dati sono stati visualizzati, quindi l'istanziazione su un nuovo tipo non ha aumentato le dimensioni del codice).

Non direi che tali tecniche siano oggi completamente obsolete, ma le implementazioni destinate a macchine desktop o server sono molto meno propense ad usarle. Per la maggior parte delle persone, l'opportunità di (per esempio) di generare più codice in linea per aumentare la velocità è più importante che risparmiare un po 'di memoria. È interessante notare che, sebbene sia inteso come un compromesso nell'usare memoria extra per aumentare la velocità, trovo che ciò abbastanza frequentemente finisca per risparmiare anche memoria. Consentendo che più codice venga generato in linea, al compilatore vengono offerte molte più opportunità per ottimizzare il codice e (ad esempio) eliminare completamente intere porzioni di codice in base alle caratteristiche del tipo effettivamente memorizzato, dove sono inclusi i metodi più vecchi ( ed eseguito) codice per supportare ogni tipo possibile, indipendentemente dal tipo effettivamente memorizzato.

Come in molte altre aree dell'ingegneria del software, si tratta in gran parte di un processo in due fasi: inizia usando il tuo miglior giudizio - ma poi usa il test vero e proprio; non fidarti troppo del tuo giudizio.

Vorrei fare attenzione a prendere molto seriamente qualcuno se tentano di semplificare eccessivamente la situazione. Le persone che non hanno esperienza significativa spesso fanno affermazioni che sono piuttosto audaci, ma non hanno molto sostegno. I sostenitori proclameranno che i modelli "migliorano la velocità di esecuzione" mentre i detrattori affermano che "causano il codice gonfiato". Mentre entrambe queste affermazioni (e molte altre) hanno una base un po ' in effetti, sono eccessivamente semplificate al punto da non avere alcun significato nel migliore dei casi e sono orribilmente fuorvianti nel peggiore dei casi.

    
risposta data 12.07.2017 - 09:09
fonte
3

L'unico svantaggio di tutti i modelli, come vengono utilizzati nell'STL, che li porta a essere vietati in diversi ambienti incorporati è il fatto che generano codice in base ai tipi trovati nel codice, questo può portare a codice inavvertito gonfiare. Se si dispone di un modello che accetta quattro valori di input, tutti gli interi e qualcuno lo utilizza con un float come uno dei parametri, il codice dell'oggetto diventerà improvvisamente più che raddoppiato.

Quindi, se stai lavorando nel mondo embedded e sei tenuto a soddisfare requisiti quali MISRA, scoprirai di essere richiesto per evitare tutti i modelli, incluso lo STL. Quindi controlla i tuoi standard di codifica prima di iniziare a usarli.

Tornare indietro nel tempo, a semplice manomissione dei nomi, se avevi un modello di funzione chiamato Fred con una firma di <T> fred(<T> a, <T> b) e il tuo codice stava chiamando int a = fred(1, 2) quindi il tuo file di mappa indicherebbe la presenza di INT32_fred_INT32_INT32 o qualcosa del genere, ma se qualcuno ha aggiunto una chiamata, ovunque nel tuo codice, a int b = fred(1, 2.) otterrai INT32_fred_INT32_FLOAT e il tuo codice salirà di dimensioni - se poi aggiungessero int b = fred(1., 2.) allora INT32_fred_FLOAT_FLOAT avrebbe apparire. (Vedi Name Mangling su questo argomento).

    
risposta data 12.07.2017 - 07:18
fonte
2

General question regarding the STL. Do you guys think that the STL should be used for data structures or would you create custom code?

Userei sempre STL.

In what scenario would you implement your own code for something that the Standard Library already does?

Se l'implementazione dell'STL a cui avevo accesso fosse gravemente obsoleta o infestata al punto da essere proibitiva da usare, prenderei in considerazione la possibilità di eseguire il mio. Questo non dovrebbe accadere in questi giorni, ma succedeva 20 anni fa:)

What are your thoughts?

Ci sono luoghi in cui l'STL non copre le funzionalità necessarie; Per le cose che la libreria standard copre, usa la libreria standard.

    
risposta data 12.07.2017 - 10:59
fonte

Leggi altre domande sui tag