c++ qué - ¿Contenedores STL o Qt?





métodos libreria (13)


Esta es una pregunta difícil de responder. Realmente puede reducirse a un argumento filosófico / subjetivo.

Habiendo dicho eso...

Recomiendo la regla "Cuando estés en Roma ... Haz lo que hacen los romanos"

Lo que significa que si estás en Qt land, codifica como lo hacen los Qt'ians. Esto no es solo para preocupaciones de legibilidad / coherencia. Considere lo que sucede si almacena todo en un contenedor stl, entonces tiene que pasar toda esa información a una función Qt. ¿De verdad quieres administrar un montón de código que copia cosas dentro y fuera de los contenedores de Qt? Su código ya depende mucho de Qt, por lo que no es como si estuviera convirtiéndolo en un "estándar" más mediante el uso de contenedores STL. ¿Y de qué sirve un contenedor si cada vez que desea utilizarlo para algo útil, debe copiarlo en el contenedor Qt correspondiente?

¿Cuáles son los pros y los contras del uso de contenedores Qt ( QMap , QVector , etc.) sobre su equivalente STL?

Puedo ver una razón para preferir Qt:

  • Los contenedores Qt se pueden pasar a otras partes de Qt. Por ejemplo, se pueden usar para llenar un QVariant y luego un QSettings (con algunas limitaciones, sin embargo, solo se QList y QMap / QHash cuyas claves son cadenas).

Hay alguna otra?

Editar : Suponiendo que la aplicación ya se basa en Qt.




Comencé usando std: :( ​​w) string y los contenedores STL exclusivamente y convirtiendo a / desde los equivalentes de Qt, pero ya he cambiado a QString y encuentro que estoy usando los contenedores de Qt cada vez más.

Cuando se trata de cadenas, QString ofrece una funcionalidad mucho más completa en comparación con std :: basic_string y es completamente consciente del Unicode. También ofrece una implementación eficiente de COW , de la que he llegado a depender mucho.

Contenedores de Qt:

  • ofrecen la misma implementación COW que en QString, que es extremadamente útil cuando se trata de usar la macro foreach de Qt (que hace una copia) y cuando se usan metatipos o señales y ranuras.
  • puede usar iteradores de estilo STL o iteradores de estilo Java
  • son transmisibles con QDataStream
  • se usan ampliamente en la API de Qt
  • tener una implementación estable a través de los sistemas operativos. Una implementación de STL debe obedecer al estándar de C ++, pero de lo contrario es libre de hacer lo que quiera (consulte la controversia de std :: string COW). Algunas implementaciones de STL son especialmente malas.
  • Proporcione hashes, que no están disponibles a menos que use TR1

El QTL tiene una filosofía diferente a la STL, que J. Blanchette resume bien : "Mientras que los contenedores de STL están optimizados para velocidad bruta, las clases de contenedores de Qt han sido cuidadosamente diseñadas para proporcionar comodidad, mínimo uso de memoria y mínima expansión de código".
El enlace anterior proporciona más detalles sobre la implementación del QTL y qué optimizaciones se utilizan.




Existe una (a veces) gran limitación en QVector. Solo puede asignar bytes de memoria (tenga en cuenta que el límite está en bytes, no en cantidad de elementos). Esto implica que tratar de asignar bloques contiguos de memoria mayores de ~ 2GB con un QVector dará lugar a un bloqueo. Esto sucede con Qt 4 y 5. std :: vector no tiene tal limitación.




Uno de los principales problemas es que la API de Qt espera que proporciones datos en los contenedores de Qt, por lo que también puedes usar los contenedores de Qt en lugar de transformarlos entre los dos.

Además, si ya está usando los contenedores Qt, podría ser un poco más óptimo usarlos exclusivamente, ya que no tendría que incluir los archivos de encabezado STL y potencialmente vincularlos en las bibliotecas STL. Sin embargo, dependiendo de su cadena de herramientas, eso puede suceder de todos modos. Puramente desde una perspectiva de diseño, la consistencia es generalmente algo bueno.




Si los datos con los que está trabajando se utilizan principalmente para conducir la interfaz de usuario basada en Qt, entonces definitivamente use contenedores Qt.

Si la mayoría de los datos se usan internamente en la aplicación, y es probable que nunca se aleje de Qt, entonces, salvo problemas de rendimiento, use los contenedores Qt, ya que hará que los bits de datos que van a la interfaz de usuario sean más fáciles de manejar.

Si los datos se utilizan principalmente junto con otras bibliotecas que solo conocen contenedores STL, entonces use contenedores STL. Si tienes esta situación, estás en problemas sin importar qué cosa, porque vas a hacer muchos cambios de ida y vuelta entre los tipos de contenedores sin importar lo que hagas.




Supongo que depende de la forma en que uses Qt. Si lo usa en todo su producto, entonces probablemente tenga sentido usar contenedores Qt. Si solo lo contiene (por ejemplo) la parte de UI, puede ser mejor usar contenedores estándar de C ++.




Mis cinco centavos: se supone que los contenedores Qt funcionan de manera similar en diferentes plataformas. Mientras que los contenedores STL dependen de la implementación de STL. Puede obtener diferentes resultados de rendimiento.

EDITAR: No estoy diciendo que STL sea "más lento", pero apunto los efectos de varios detalles de implementación.
Por favor revisa this , y luego tal vez this .
Y no es un problema real de STL. Obviamente, si tiene una diferencia significativa en el rendimiento, entonces hay un problema en el código que usa STL.




Los contenedores de Qt son más limitados que los de STL. Algunos ejemplos de dónde los STL son superiores (todos estos en el pasado):

  • STL está estandarizado, no cambia con cada versión de Qt (Qt 2 tenía QList (basado en puntero) y QValueList (basado en valor); Qt 3 tenía QPtrList y QValueList ; Qt 4 ahora tenía QList , y no se parecía en nada a QPtrList o QValueList ).
    Incluso si termina usando los contenedores Qt, use el subconjunto API compatible con STL (es decir, push_back() , no append() ; front() , no first() , ...) para evitar volver a portarlos, vuelva Qt 5 En las transiciones Qt2-> 3 y Qt3-> 4, los cambios en los contenedores Qt se encontraban entre los que requerían la mayoría del cambio de código.
  • Los contenedores bidireccionales STL tienen todos rbegin() / rend() , lo que hace que la iteración inversa sea simétrica a la iteración directa. No todos los contenedores Qt los tienen (los asociativos no), por lo que la iteración inversa es innecesariamente complicada.
  • Los contenedores STL tienen range- insert() de tipos de iteradores diferentes, pero compatibles, haciendo que std::copy() mucho menos necesario.
  • Los contenedores STL tienen un argumento de plantilla de Allocator , lo que hace que la gestión de memoria personalizada sea trivial (se requiere typedef), en comparación con Qt (se requiere el fork de QLineEdit para s/QString/secqstring/ ). EDIT 20171220 : Esto reduce Qt de los avances en el diseño del asignador siguiendo C ++ 11 y C ++ 17, cf. por ejemplo, la charla de John Lakos ( parte 2 ).
  • No hay Qt equivalente a std::deque .
  • std::list tiene splice() . Cada vez que me encuentro usando std::list , es porque necesito splice() .
  • std::stack , std::queue agregan apropiadamente su contenedor subyacente, y no lo heredan, como lo hace QStack , QQueue .
  • QSet es como std::unordered_set , no como std::set .
  • QList es simplemente extraño .

Muchos de los anteriores podrían resolverse con bastante facilidad en Qt , pero la biblioteca de contenedores en Qt parece experimentar una falta de enfoque de desarrollo en este momento.

EDIT 20150106 : después de haber pasado un tiempo tratando de llevar C ++ 11-soporte para Qt 5 clases de contenedor, he decidido que no vale la pena el trabajo. Si nos fijamos en el trabajo que se está poniendo en las implementaciones de la biblioteca estándar de C ++, está bastante claro que las clases de Qt nunca se pondrán al día. Hemos lanzado Qt 5.4 ahora y QVector aún no mueve elementos en reasignaciones, no tiene emplace_back() ni rvalue- push_back() ... También QOptional recientemente una plantilla de clase QOptional , esperando std::optional lugar . Del mismo modo para std::unique_ptr . Espero que esa tendencia continúe.




Además de la diferencia de COW, los contenedores STL son mucho más compatibles con una variedad de plataformas. Qt es lo suficientemente portátil si limita su trabajo a plataformas "convencionales", pero el STL también está disponible en muchas otras plataformas más oscuras (por ejemplo, los DSP de Texas Instruments).

Debido a que el STL es estándar en lugar de estar controlado por una sola corporación, en general hay más programadores que pueden leer, comprender y modificar fácilmente el código STL y más recursos (libros, foros en línea, conferencias, etc.) para apoyarlos en haciendo esto que hay para Qt. Eso no quiere decir que uno deba alejarse de Qt solo por esta razón; solo que, en igualdad de condiciones, debe usar el STL por defecto, pero por supuesto todas las cosas rara vez son iguales, por lo que tendrá que decidir en su propio contexto lo que tenga más sentido.

Con respecto a la respuesta de AlexKR: el rendimiento de STL está garantizado dentro de los límites, pero una implementación determinada puede hacer uso de detalles dependientes de la plataforma para acelerar su STL. Entonces, en ese sentido, puede obtener resultados diferentes en diferentes plataformas, pero nunca será más lento que la garantía explícita (errores de módulo).




La razón principal para ir con contenedores STL para mí es si necesita un asignador personalizado para reutilizar la memoria en contenedores muy grandes. Supongamos, por ejemplo, que tiene un QMap que almacena 1000000 entradas (pares clave / valor). En Qt eso implica exactamente 1000000 millones de asignaciones (llamadas new ) sin importar qué. En STL siempre puede crear un asignador personalizado que internamente asigna toda esa memoria a la vez y asignarla a cada entrada a medida que se llena el mapa.

Mi consejo es usar contenedores STL al escribir algoritmos críticos para el rendimiento en la lógica empresarial y luego convertirlos a contenedores Qt cuando los resultados estén listos para mostrarlos en los controles y formularios de la interfaz de usuario si es necesario.




Soy de la opinión de que STL es una excelente pieza de software, sin embargo, si tengo que hacer algo de programación relacionada con KDE o Qt, entonces Qt es el camino a seguir. También depende del compilador que está utilizando, con GCC STL funciona bastante bien; sin embargo, si tiene que usar decir SUN Studio CC entonces STL probablemente le traerá dolores de cabeza debido al compilador, no al STL per se. En ese caso, dado que el compilador hará que te duela la cabeza, utiliza Qt para ahorrarte el problema. Solo mis 2 centavos ...




Contenedores STL:

  • Tener garantías de rendimiento
  • Se puede usar en algoritmos STL que también tienen garantías de rendimiento
  • Puede ser aprovechado por bibliotecas C ++ de terceros como Boost
  • Son estándares, y es probable que sobrevivan a soluciones patentadas
  • Fomentar la programación genérica de algoritmos y estructuras de datos. Si escribe nuevos algoritmos y estructuras de datos que se ajusten a STL, puede aprovechar lo que STL ya proporciona sin costo.



Bueno, veo que en tu segunda solución cambiaste de cin a scanf , que fue la primera sugerencia que te iba a hacer (cin is sloooooooooooow) Ahora, si cambia de scanf a fgets , verá otro aumento en el rendimiento: fgets es la función C ++ más rápida para la entrada de cadenas.

Por cierto, no sabía acerca de esa cosa de sincronización, bonito. Pero aún deberías probar fgets .







c++ qt stl