¿Es práctico abandonar STL en el desarrollo de C ++? [cerrado]

19

Sé que en algunas áreas (industria de juegos, por ejemplo), no se recomienda STL. Entonces mi pregunta es: ¿es realmente una buena práctica no usar STL en algunos casos? Si es así, ¿cuáles son las principales razones para no usar el STL moderno de C ++?

Capitán JH
fuente
pregunta relacionada
fredoverflow
Algunos de mis colegas argumentan que el iterador dificulta la depuración, porque a veces no es fácil intervenir, y esto también se aplica a la lambda. Cual es tu respuesta
CaptainJH
En cuanto a omitir cosas durante la depuración, consulte, por ejemplo: stackoverflow.com/questions/2062881/…
Martin Ba
Esta parece una buena pregunta. Tal vez alguien podría agregar "¿Por qué un proyecto elegiría no usar el STL?"
Matthew James Briggs

Respuestas:

25
  • Solo se me ocurre una razón válida y es realmente raro: el tiempo real difícil. Muchas cosas en la biblioteca estándar asignan memoria internamente y eso no es lo suficientemente determinista para aplicaciones en tiempo real difíciles, por lo que deben evitarse. Estas aplicaciones suelen ser bastante simples, aunque tardan un tiempo desproporcionado en desarrollarse debido a la rigurosa revisión y prueba.

  • Puedo pensar en una razón inválida, pero muy común: los desarrolladores que no entienden la complejidad computacional, usan indebidamente STL y luego culpan a la biblioteca.

    STL suele ser más rápido en tiempo de ejecución que las soluciones de estilo C con punteros de devolución de llamada o soluciones basadas en polimorfismo con métodos virtuales ( consulte también la nota clave de Bjarne Stroustrup ). Sin embargo, cuando el desarrollador no comprende las especificaciones de complejidad dadas y hace un mal uso de la biblioteca creando algo así como el vector de vectores de algunos objetos complejos (¡en C ++ 11 ya no es un problema!), Causa un problema de rendimiento y luego se defiende con "ves, los vectores son bastante lentos", puede causar una percepción de que la biblioteca estándar es lenta. Y una vez que los gerentes obtienen esa percepción, puede vivir mucho tiempo en la organización.

  • Obviamente, no puede usar nada que la plataforma a la que apunta no sea compatible. Sin embargo, actualmente apuntamos a las cuatro plataformas móviles más comunes (Android, iOS, Bada y WinCE anterior) y usamos la biblioteca estándar y algunas partes de Boost en todas ellas.

    Gran parte de la biblioteca estándar solía no ser compatible con Microsoft a principios de WinCE (los iostreams IIRC solo salieron con Visual Studio 2005), pero en su lugar era posible usar STLport mucho antes. Y generalmente puede hacer que se compile para cualquier cosa. Entonces llamaría a esta razón inválida también.

    Además, durante bastante tiempo no es "STL", sino ANSI C ++ Standard Library. Está definido por el mismo documento estándar que define el lenguaje en sí. Todo lo que no lo admite no merece llamarse C ++.

Jan Hudec
fuente
66
El primer argumento (en tiempo real) no es específico de las partes STL de la Biblioteca estándar. sprintfa menudo asigna memoria también. En plataformas en tiempo real, las funciones de biblioteca estándar también tienen límites deterministas. Esto dificulta las implementaciones de C ++ en tiempo real: tendrías que desarrollar cuidadosamente una biblioteca estándar completa de C ++, que es más trabajo que solo la pequeña biblioteca estándar de C ++.
MSalters
@MSalters: Claro, muchas cosas no se pueden usar bajo requisitos en tiempo real. Incluso algunas características del lenguaje como las excepciones no pueden. Aún así, C ++ es un gran lenguaje para estos sistemas, ya que puede combinar el rendimiento y el control preciso con fuertes salvaguardas (RAII es la característica más importante para eso).
Jan Hudec
@ JanHudec: De hecho, es por eso que las partes STL solo son necesarias para implementaciones "alojadas" de C ++.
MSalters
7

Estoy usando STL y boost por muchos años ya. Si quisiera abandonarlo y usar mis herramientas personalizadas, la motivación sería:

  1. Reducción del tiempo de compilación (75%). Solo incluir iostreams puede agregar 1 millón de líneas de código a su módulo. Sí, los encabezados precompilados ayudan mucho, pero aún así ralentiza mucho la compilación en grandes proyectos. A la larga, desperdicia mucho tiempo de cualquiera que trabaje en él.
  2. Actuación. (25%) STL está escrito para funcionar en general, pero puede optimizar sus estructuras para que funcionen exactamente como lo desee. Por ejemplo, puede tener estructuras de datos con millones de cadenas cortas. Puede ser mucho más rápido usar una clase de cadena personalizada basada en el principio de boost :: small_vector (vector local de datos estático pequeño, asignación dinámica solo para cadenas más grandes), este tipo de cambios puede hacer que las secciones críticas del código funcionen muchas veces más rápido.
Marwin
fuente
1
SSO ya es común.
Deduplicador el
para la posteridad: SSO -> optimización de cadenas pequeñas, es decir, la mayoría (¿todas?) Las implementaciones std :: string mantienen cadenas pequeñas en la pila y cambian al montón si es necesario
azul
Los tiempos de compilación son importantes
usuario 1754322
4

Hay una gran razón válida para no usar la biblioteca de plantillas estándar de C ++: una de sus plataformas de destino no tiene una implementación totalmente compatible (o ninguna implementación) y usted sabe que no obtendrá una. dentro de los próximos años.

Patricio
fuente
3
Aka "no lo uses cuando no lo tienes", lo cual tiene sentido, de verdad. :)
Xeo
44
Dado que la biblioteca estándar C ++ 03 está diseñada para implementarse solo en términos de la biblioteca ANSI C89, ¿hay alguna plataforma en la que no pueda obtener al menos STLPort ?
Jan Hudec
@ JanHudec Creo que hay plataformas sin STL porque no tienen suficiente memoria para manejar todo. Por lo general, también les falta alguna otra funcionalidad de C ++ (por ejemplo, excepciones).
Sulthan
2
@Sulthan: Para los microcontroladores, entiendo un poco, pero por lo general caen en la categoría de "tiempo real difícil". Para cualquier otra cosa, eso es principalmente ideas preconcebidas, porque STL generalmente es tan eficiente tanto en memoria y rendimiento como el código hecho a mano. Una gran cantidad de línea puede causar un binario más grande, pero eso incluso podría evitarse mediante una implementación cuidadosa a un costo de rendimiento (que también tendría una solución hecha a mano). Las excepciones que faltan también son preconcepción o pereza, porque se necesita esfuerzo para definir e implementar la excepción ABI.
Jan Hudec
4

No sé acerca de la complejidad (eficiencia de implementación), pero estoy usando contenedores y cadenas Qt ampliamente en lugar de los estándar y funcionan bien. También encuentro que la implementación Qt de conjuntos y listas es más fácil de usar.

Por lo tanto, puede ser práctico abandonar el STL si puede usar otra biblioteca que se ajuste a sus necesidades.

Giorgio
fuente
2
los equivalentes de Qt se crearon hace mucho tiempo cuando no había implementaciones de STL que estuvieran a) disponibles, o b) ninguna buena. Esa es la única razón por la que todavía se usan, nada contra el STL de hoy.
gbjbaanb
1
@Giorgio: el problema está en las aplicaciones complejas, donde se combinan varias bibliotecas. Los contenedores STL, siendo estándar, forman una lingua franca . Más precisamente, son sus convenciones las que lo hacen. El ejemplo más conocido es Boost. Puede funcionar en contenedores STL. también puede funcionar en contenedores Qt, pero solo porque Qt sigue las convenciones de STL, por ejemploQList<T>::iterator
MSalters
3
No lo rechacé, pero veo una razón: no responde la pregunta. Dijiste que hay cosas para usar en lugar de STL, está bien, pero esa no es una razón para evitar STL. Además de cualquier razón para evitar STL, probablemente se aplica a Qt, MFC y otras bibliotecas similares, o incluso más.
Jan Hudec
3
@NoOne: entendemos que estás acostumbrado a camelcase, no a snakecase, pero eso no empeora este último. Y de los tres nombres de funciones que critica, el primero es perfectamente descriptivo para cualquiera que tenga algo que ver con las cadenas en C, y los otros dos son heredados de C, no los discutirá.
Deduplicador el
1
@NoOne: Como dije, entiendo totalmente que te sientas más cómodo con CamelCase.
Deduplicador
3

Patrick ha mencionado la razón para no usar todo el STL, es decir, que su (s) plataforma (s) no tiene uno.

En general, creo que la pregunta no tiene sentido. En general, no es una decisión de todo o nada, sino de elegir y elegir. Es posible que decida utilizar los contenedores y los algoritmos, pero decida usar algo fuera de Std Lib para cadenas e I / O.

Martin Ba
fuente
3

No es práctico, a menos que haya una razón importante para hacerlo. Algunas de las razones en las que puedo pensar incluyen solo la implementación parcial o inexistente de STL (o cualquier otra parte de la biblioteca estándar) o una limitación de recursos (memoria, velocidad de CPU, almacenamiento, ...) que debe sortear rodar sus propias herramientas que se adhieren a lo que necesita lograr.

En la industria de los juegos, la mayoría de los estudios (incluso más pequeños hasta cierto punto) tienen sus bibliotecas internas e implementaciones de muchas partes de la biblioteca estándar que están muy adaptadas para la plataforma objetivo y, en algunos casos, para el engnie objetivo o incluso para el juego en sí. En pocas palabras, al desarrollar un juego para consolas, el hardware está muy limitado por los estándares actuales. Hay miles y miles de líneas de ensamblaje hecho a mano por una razón. Es muy importante minimizar todo tipo de huellas de recursos en su código para que el juego se ejecute más rápido, lo que permite más contenido en el mundo del juego (o en un mundo más grande, por ejemplo), lo que con suerte resulta en un mejor producto.

"Cada juego exitoso comienza implementando su propia implementación de la lista vinculada".

zxcdw
fuente
1
Me imagino que cada juego exitoso comienza escribiendo código usando la biblioteca estándar y luego solo optimizando el código una vez que el juego ha sido ampliamente perfilado. La optimización antes de tener datos de perfil que indiquen lo que necesita optimización no tiene sentido.
Cromulent
Cierto. La última frase era solo una obra de teatro sobre la forma "antigua" de escribir juegos a principios de los 90, cuando C ++ no estaba tan ampliamente implementado y el ensamblaje + C era el camino a seguir. Quizás debería haberlo dejado más claro. Sin embargo, se aplica bien a la industria del juego en las consolas, la mayoría de los algoritmos y las estructuras de datos están escritas a mano de forma predeterminada porque cada byte y ciclo cuenta (sí, incluso a expensas de la mantenibilidad / portabilidad / lo que sea).
zxcdw
2
Debería decirse que es más una vieja experiencia de vida. El optimizador moderno generalmente generará un mejor ensamblaje a partir de un código fácil de mantener que el programador hará a mano y las plantillas genéricas como en STL o Boost a menudo se alinean con un código tan eficiente como el revestimiento especial de todo a mano. Pero hay una gran cantidad de código que comenzó en momentos en que ese no era el caso y muchas personas que aprendieron el oficio esos días y siguen trabajando de esa manera a pesar de que ya no tiene sentido.
Jan Hudec
2
@JanHudec La cuestión es que las implementaciones (y los comportamientos también, de hecho) deben adaptarse mucho para la tarea. Simplemente no puede ahorrar algunas docenas de bytes aquí y allá (arruinando la localidad de referencia), coloque algunas ramas para validar la entrada (predicciones erróneas de rama y errores de caché de instrucciones) y suponga que el compilador sabe cómo vectorizar sus estructuras de datos de manera óptima para aprovechar SIMD (no lo hará, o al menos debe verificar que lo que intenta sea correcto). Por supuesto, escribir software en tiempo real en una PC no es tan estricto, siempre puedes agregar una CPU más rápida. No en consolas.
zxcdw