È pratico abbandonare STL nello sviluppo di C ++? [chiuso]


19

So che in alcune aree (industria dei giochi, ad esempio), STL non è raccomandato. Quindi la mia domanda è: è davvero una buona pratica non usare STL in alcuni casi? In tal caso, quali sono i principali motivi per non utilizzare il moderno STL del C ++?



alcuni dei miei colleghi sostengono che l'iteratore rende il debug più difficile, perché a volte non è facile intervenire e questo si applica anche al lambda. Qual è la tua risposta?
CaptainJH,

Per quanto riguarda saltare le cose durante il debug, vedere, ad esempio: stackoverflow.com/questions/2062881/…
Martin Ba

Questa sembra una buona domanda. Forse qualcuno potrebbe aggiungere "Perché un progetto dovrebbe scegliere di non utilizzare l'STL?"
Matthew James Briggs,

Risposte:


25
  • Mi viene in mente solo un motivo valido ed è davvero raro: tempo reale difficile. Molte cose nella libreria standard allocano la memoria internamente e questo non è abbastanza deterministico per le applicazioni in tempo reale, quindi devono essere evitati. Queste applicazioni sono in genere piuttosto semplici, anche se richiedono tempi sproporzionati per lo sviluppo a causa di test e revisioni molto rigorosi.

  • Mi viene in mente una ragione non valida, ma molto comune: gli sviluppatori che non comprendono la complessità computazionale, usano in modo improprio STL e quindi danno la colpa alla libreria.

    L'STL è solitamente più veloce in fase di runtime rispetto alle soluzioni in stile C con puntatori di callback o soluzioni basate sul polimorfismo con metodi virtuali ( vedi anche questo keynote di Bjarne Stroustrup ). Tuttavia, quando lo sviluppatore non capisce le specifiche di complessità fornite e abusa della libreria creando qualcosa come vettore di vettori di alcuni oggetti complessi (in C ++ 11 non è più un problema, però!), Causa un problema di prestazioni e si difende con "vedi, i vettori sono piuttosto lenti", può causare la percezione che la libreria standard sia lenta. E una volta che i manager ottengono tale percezione, possono vivere molto a lungo nell'organizzazione.

  • Ovviamente non puoi usare nulla che la piattaforma che stai prendendo di mira non supporta. Tuttavia, al momento stiamo prendendo di mira quattro piattaforme mobili più comuni (Android, iOS, Bada e WinCE precedente) e utilizziamo la libreria standard e alcune parti di Boost su tutte.

    Gran parte della libreria standard non era supportata da Microsoft all'inizio di WinCE (gli iostreams IIRC uscivano solo con Visual Studio 2005), ma era possibile utilizzare STLport molto prima. E di solito puoi farlo compilare per qualsiasi cosa. Quindi definirei invalido anche questo motivo.

    Inoltre, per molto tempo non è "STL", ma ANSI C ++ Standard Library. È definito dallo stesso documento standard che definisce la lingua stessa. Tutto ciò che non lo supporta non merita davvero di essere chiamato C ++.


6
Il primo argomento (in tempo reale) non è specifico per le parti STL della libreria standard. sprintfspesso alloca anche la memoria. Su piattaforme in tempo reale, le funzioni di libreria standard hanno anche limiti deterministici. Questo rende difficili le implementazioni C ++ in tempo reale: dovresti sviluppare attentamente un'intera libreria standard C ++, che è più lavoro che solo la piccola libreria standard C.
Saluti

@MSalters: Certo, molte cose non possono essere utilizzate con requisiti in tempo reale. Anche alcune funzionalità linguistiche come le eccezioni non possono. Tuttavia il C ++ è un linguaggio eccezionale per questi sistemi, perché può combinare prestazioni e controllo preciso con solide protezioni (RAII è la caratteristica più importante per questo).
Jan Hudec,

@JanHudec: In effetti, ecco perché le parti STL sono necessarie solo per implementazioni "ospitate" di C ++.
Salteri il

7

Sto usando STL e boost già da molti anni. Se volessi abbandonarlo e utilizzare i miei strumenti personalizzati, la motivazione sarebbe:

  1. Riduzione del tempo di compilazione (75%). Solo l'inclusione di iostreams può aggiungere 1 milione di righe di codice al tuo modulo. Sì, le intestazioni precompilate aiutano molto, ma rallentano ancora molto la compilazione nei grandi progetti. A lungo termine, fa perdere molto tempo a chiunque ci lavori.
  2. Prestazione. (25%) STL è scritto per funzionare in generale, ma è possibile ottimizzare le strutture affinché funzionino esattamente come si desidera. Ad esempio, potresti avere una struttura dati con milioni di stringhe brevi. Potrebbe essere molto più veloce utilizzare la classe di stringhe personalizzata basata sul principio di boost :: small_vector (piccolo vettore locale statico di dati, allocazione dinamica solo per stringhe più grandi), questo tipo di modifiche può far funzionare le sezioni critiche del codice molte volte più velocemente.

1
SSO è già comune.
Deduplicatore

per i posteri: SSO -> ottimizzazione delle stringhe piccole, ovvero la maggior parte (tutte?) le implementazioni std :: string tengono piccole stringhe nello stack e passano all'heap se necessario
blu

I tempi di compilazione sono importanti
user1754322,

4

Esiste un motivo valido per non utilizzare la libreria di modelli standard C ++: una delle tue piattaforme di destinazione non ha un'implementazione pienamente conforme (o nessuna implementazione) e sai che non ne otterrà una entro i prossimi anni.


3
Aka "non usarlo quando non lo hai", il che ha davvero senso. :)
Xeo,

4
Dato che la libreria standard C ++ 03 è progettata per essere implementata solo in termini di libreria ANSI C89, esiste una piattaforma in cui non è possibile ottenere almeno STLPort ?
Jan Hudec,

@JanHudec Credo che ci siano piattaforme senza STL perché non hanno memoria sufficiente per gestire il tutto. Di solito mancano anche alcune altre funzionalità C ++ (es. Eccezioni).
Sulthan,

2
@Sulthan: Per i microcontrollori capisco, ma quelli rientrano nella categoria "hard realtime" di solito. Per ogni altra cosa, questo è per lo più preconcetti, perché STL è di solito altrettanto efficiente sia in termini di memoria che di prestazioni rispetto al codice realizzato a mano. Molti allineamenti possono causare binari più grandi, ma ciò potrebbe persino essere evitato con un'attenta implementazione a un certo costo prestazionale (che avrebbe anche una soluzione artigianale). Le eccezioni mancanti sono anche preconcetto o pigrizia, perché ci vuole sforzo per definire e attuare l'eccezione ABI.
Jan Hudec,

4

Non conosco la complessità (efficienza dell'implementazione) ma sto usando ampiamente contenitori e stringhe Qt invece di quelli standard e funzionano bene. Trovo anche l'implementazione Qt di set ed elenchi più facile da usare.

Pertanto, può essere pratico abbandonare l'STL se è possibile utilizzare un'altra libreria adatta alle proprie esigenze.


2
gli equivalenti Qt sono stati creati molto tempo fa quando non c'erano implementazioni STL che erano o a) disponibili, o b) qualsiasi bene. Questa è l'unica ragione per cui sono ancora usati, nulla contro la STL di oggi.
gbjbaanb,

1
@Giorgio: il problema è nelle applicazioni complesse, in cui stai combinando più librerie. I contenitori STL, essendo standard, formano una lingua franca . Più precisamente, sono le loro convenzioni che lo fanno. L'esempio più noto è Boost. Può funzionare su contenitori STL. può funzionare anche su contenitori Qt, ma solo perché Qt ha seguito le convenzioni STL - es.QList<T>::iterator
MSalters il

3
Non ho votato a fondo, ma vedo una ragione: non risponde alla domanda. Hai detto che ci sono cose da usare al posto di STL, va bene, ma non è un motivo per evitare STL. Oltre a qualsiasi motivo per evitare STL, probabilmente si applica anche a Qt, MFC e altre librerie simili o anche di più.
Jan Hudec,

3
@NoOne: Capiamo che sei abituato a camelcase, non a scatto, ma ciò non peggiora quest'ultimo. E dei tre nomi di funzione che critichi, il primo è perfettamente descrittivo per chiunque abbia a che fare con le stringhe c, e gli altri due sono ereditati da C, non ne discuteranno.
Deduplicatore

1
@NoOne: come ho detto, capisco perfettamente che sei più a tuo agio con CamelCase.
Deduplicatore

3

Patrick ha menzionato il motivo per non utilizzare l'intero STL, vale a dire che le piattaforme non ne hanno una.

Tutto sommato, penso che alla questione manchi il punto. Per lo più non è una decisione tutto o niente, ma una scelta. Potresti decidere di utilizzare i contenitori e gli algoritmi, ma decidere di utilizzare qualcosa al di fuori dello Std Lib per stringhe e I / O.


3

Non è pratico, a meno che non ci sia una ragione pesante per farlo. Alcuni di questi motivi che posso pensare includono solo un'implementazione parziale o mancante di STL (o qualsiasi altra parte della libreria standard) o una limitazione delle risorse (memoria, velocità della CPU, memoria, ...) che devi aggirare rotolare i tuoi strumenti che aderiscono a ciò che devi realizzare.

Nell'industria dei videogiochi la maggior parte degli studi (anche più piccoli in una certa misura) hanno le loro librerie interne e le implementazioni di molte parti di librerie standard che sono altamente personalizzate per la piattaforma di destinazione e in alcuni casi il target di gioco o persino il gioco stesso. In poche parole, quando si sviluppa un gioco per console, l'hardware è molto limitato dagli standard odierni. Ci sono migliaia e migliaia di linee di assemblaggio artigianale per un motivo. È molto importante ridurre al minimo tutti i tipi di impronte di risorse nel tuo codice in modo che il gioco funzioni più velocemente, il che consente più contenuti nel mondo di gioco (o un mondo più grande, ad esempio) che si spera si traduca in un prodotto migliore.

"Ogni gioco di successo inizia con l'implementazione della tua lista di link collegati."


1
Immagino che ogni gioco di successo inizi scrivendo il codice utilizzando la libreria standard e quindi ottimizzando il codice solo dopo che il gioco è stato ampiamente profilato. L'ottimizzazione prima di disporre di dati di profilazione che indicano ciò che è necessario ottimizzare è inutile.
Cromulent,

Vero. L'ultima frase era solo un gioco sul modo "antico" di scrivere giochi nei primi anni '90 circa, quando C ++ non era così diffuso e assembly + C era la strada da percorrere. Forse avrei dovuto renderlo più chiaro. Si applica bene all'industria dei giochi nelle console, la maggior parte degli algoritmi e delle strutture di dati sono scritti a mano di default perché ogni byte e ciclo conta (sì, anche a spese di manutenibilità / portabilità / qualunque cosa).
zxcdw,

2
Va detto, che è più una vecchia esperienza vivente. L'ottimizzatore moderno di solito genera un assemblaggio migliore da un semplice codice gestibile rispetto a quello che farà il programmatore a mano e i modelli generici come in STL o Boost spesso sono in linea con un codice efficiente quanto l'involucro speciale tutto a mano. Ma c'è un sacco di codice che è iniziato in tempi in cui non era così e molte persone hanno imparato il mestiere in quei giorni e continuano a lavorare in quel modo anche se non ha più senso.
Jan Hudec,

2
@JanHudec Il fatto è che le implementazioni (e anche i comportamenti) devono essere molto su misura per il compito. Semplicemente non puoi risparmiare qualche decina di byte qua e là (rovinando la località di riferimento), rilasciare alcuni rami per convalidare l'input (errori di lettura dei rami e errori nella cache delle istruzioni) e assumere che il compilatore sappia come vettorializzare le tue strutture di dati sfruttare in modo ottimale SIMD (non lo farà, o almeno devi verificare che ciò che tenta sia corretto). Ovviamente scrivere software in tempo reale su un PC non è così rigoroso, puoi sempre lanciare una CPU più veloce. Non nelle console.
zxcdw,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.