Conteneurs STL ou Qt?

189

Quels sont les avantages et les inconvénients de l' utilisation des conteneurs Qt ( QMap, QVector, etc.) sur leur équivalent STL?

Je peux voir une raison de préférer Qt:

  • Les conteneurs Qt peuvent être transmis à d'autres parties de Qt. Par exemple, ils peuvent être utilisés pour remplir a QVariantpuis a QSettings(avec une certaine limitation cependant, seuls QListet QMap/ QHashdont les clés sont des chaînes sont acceptés).

Y en a-t-il un autre?

Edit : en supposant que l'application repose déjà sur Qt.

Julien-L
la source

Réponses:

140

J'ai commencé par utiliser std::(w)stringet les conteneurs STL exclusivement et en convertissant vers / depuis les équivalents Qt, mais je suis déjà passé QStringet je trouve que j'utilise de plus en plus les conteneurs Qt.

En ce qui concerne les chaînes, QStringoffre des fonctionnalités beaucoup plus complètes par rapport à std::basic_stringet il est entièrement compatible Unicode. Il offre également une implémentation efficace de COW , sur laquelle je me fie beaucoup.

Les conteneurs de Qt:

  • offrent la même implémentation COW que dans QString, ce qui est extrêmement utile lorsqu'il s'agit d'utiliser la foreachmacro de Qt (qui fait une copie) et lors de l'utilisation de méta-types ou de signaux et de slots.
  • peut utiliser des itérateurs de style STL ou des itérateurs de style Java
  • sont diffusables avec QDataStream
  • sont largement utilisés dans l'API de Qt
  • ont une implémentation stable sur tous les systèmes d'exploitation. Une implémentation STL doit obéir au standard C ++, mais est par ailleurs libre de faire ce qu'il veut (voir la std::stringcontroverse COW). Certaines implémentations STL sont particulièrement mauvaises.
  • fournir des hachages, qui ne sont disponibles que si vous utilisez TR1

Le QTL a une philosophie différente de la STL, qui est bien résumée par J. Blanchette: "Alors que les conteneurs de STL sont optimisés pour la vitesse brute, les classes de conteneurs de Qt ont été soigneusement conçues pour offrir une commodité, une utilisation minimale de la mémoire et une expansion de code minimale."
Le lien ci-dessus fournit plus de détails sur l'implémentation du QTL et les optimisations utilisées.

rpg
la source
12
Dans le nouveau standard c ++, 0x COW est à peu près hors de propos.
16
re: "soigneusement conçu pour fournir une [...] utilisation minimale de la mémoire". Vous ne devriez pas croire le marketing. Profil QList<double>sur une architecture 32 bits pour une utilisation de la mémoire pour voir par vous-même.
Marc Mutz - mmutz
11
"Il offre également une implémentation COW efficace": COW n'est pas si efficace quand il s'agit d'applications multithread ...
Grizzly
5
@ MarcMutz-mmutz essayez de profiler QVectorau lieu de QList. Il y a une jolie explication Qt, que QList est conçu pour stocker des pointeurs sur des objets. Ainsi, chaque élément double créé dynamiquement et le pointeur vers cet élément est stocké QList. QList est conçu comme un conteneur «intermédiaire» entre le vecteur et la liste chaînée. Il n'est pas conçu pour les cas critiques de mémoire / performances.
Dmitry Sazonov
2
@ user1095108 Il n'y a rien de mal à cela. Allez utiliser le stl. Certains d'entre nous préfèrent écrire rapidement un code correct. Il n'y a rien de mal à cela non plus.
weberc2
181

C'est une question à laquelle il est difficile de répondre. Cela peut vraiment se résumer à un argument philosophique / subjectif.

Cela étant dit...

Je recommande la règle "Quand à Rome ... fais comme les Romains"

Ce qui signifie que si vous êtes sur le terrain Qt, codez comme le font les Qt'ians. Ce n'est pas seulement pour des problèmes de lisibilité / cohérence. Considérez ce qui se passe si vous stockez tout dans un conteneur stl, vous devez alors transmettre toutes ces données à une fonction Qt. Voulez-vous vraiment gérer un tas de code qui copie des éléments dans / hors des conteneurs Qt. Votre code dépend déjà fortement de Qt, donc ce n'est pas comme si vous le rendiez plus «standard» en utilisant des conteneurs stl. Et quel est l'intérêt d'un conteneur si à chaque fois que vous souhaitez l'utiliser pour quelque chose d'utile, vous devez le copier dans le conteneur Qt correspondant?

Doug T.
la source
1
+1 vous avez tout à fait raison, c'est ce que j'ai essayé d'expliquer dans ma question ("Je peux voir une raison de préférer Qt") donc je l'ai légèrement modifiée. Merci
Julien-L
Absolument bien dit. Si vous faites QT, utilisez les trucs QT! Imaginez le moment "WTF" pour le mainteneur lorsqu'il ouvre une application QT et voit QT et STL utilisés de manière interchangeable. Cela pourrait finir par être un cauchemar (inutile).
It'sPete
5
@ It'sPete STL fait partie de la norme; QT ne l'est pas. Tout code utilisant le standard ne doit jamais déclencher un moment "WTF".
Alice
6
Les Romains mirent leurs captifs au Colisée et les chassèrent avec des lions. Si vous savez mieux, ne suivez pas les habitudes locales. C'est aussi vrai dans Qt que cela aurait été pour l'homme moderne dans l'Empire romain ...
Marc Mutz - mmutz
1
@mmutz vous dites que comme si c'était une mauvaise chose, j'aimerais mettre du code que j'ai trouvé dans ce Colisée et regarder l'émission
slf
67

Les conteneurs Qt sont plus limités que ceux de la STL. Quelques exemples où les STL sont supérieurs (tous ceux que j'ai rencontrés dans le passé):

  • STL est standardisé, ne change pas avec chaque version de Qt (Qt 2 avait QList(basé sur un pointeur) et QValueList(basé sur une valeur); Qt 3 avait QPtrListet QValueList; Qt 4 a maintenantQList , et ce n'est rien du tout comme QPtrList ou QValueList ). Qt 6 aura un QListqui est QVectortout QVectorsera dépréciée . (. -À- dire même si vous finissez par utiliser les conteneurs Qt, utilisez le sous - ensemble de l' API STL compatible push_back(), non append(), front()non first(), ...) afin d' éviter le portage viennent encore une fois Qt 6. Dans les deux Qt2-> 3 et Qt3-> 4 transitions, les changements dans les conteneurs Qt étaient parmi ceux nécessitant le plus de désabonnement de code. J'attends la même chose pour Qt5-> 6.
  • Les conteneurs bidirectionnels STL ont tous rbegin()/ rend(), ce qui rend l'itération inverse symétrique à l'itération directe. Tous les conteneurs Qt n'en ont pas (les associatifs n'en ont pas), donc l'itération inverse est inutilement compliquée.
  • Les conteneurs STL ont une gamme insert()de types d'itérateurs différents, mais compatibles, ce qui les rend std::copy()beaucoup moins souvent nécessaires.
  • Les conteneurs STL ont un Allocatorargument de modèle, ce qui rend la gestion de la mémoire personnalisée triviale (typedef requis), par rapport à Qt (fork de QLineEditrequis pour s/QString/secqstring/). EDIT 20171220 : Cela coupe Qt des avancées dans la conception d'allocateurs suivant C ++ 11 et C ++ 17, cf. Par exemple, le discours de John Lakos ( partie 2 ).
  • Il n'y a pas d'équivalent Qt à std::deque.
  • std::lista splice(). Chaque fois que je me retrouve à utiliser std::list, c'est parce que j'ai besoin splice().
  • std::stack, std::queueAgréger correctement leur contenant sous - jacent, et ne pas hériter, comme QStack, QQueuefaire.
  • QSetest comme std::unordered_set, pas comme std::set.
  • QListest juste bizarre .

Beaucoup de ce qui précède pourrait être résolu assez facilement dans Qt , mais la bibliothèque de conteneurs de Qt semble éprouver un manque de concentration sur le développement pour le moment.

EDIT 20150106 : Après avoir passé un certain temps à essayer d'apporter le support C ++ 11 aux classes de conteneurs Qt 5, j'ai décidé que cela ne valait pas le travail. Si vous regardez le travail qui est mis en œuvre dans les implémentations de bibliothèques standard C ++, il est tout à fait clair que les classes Qt ne rattraperont jamais. Nous avons publié Qt 5.4 maintenant etne déplaceQVector toujours pas les éléments sur les réallocations, n'a pasemplace_back()ou rvalue-push_back()... Nous avons également récemment rejeté unQOptional modèle de classe, en attendant à la std::optionalplace. De même pour std::unique_ptr. J'espère que cette tendance se poursuivra.

MODIFIER 20201009 : Venez Qt 6, ils nouveau leurs conteneurs de manière incompatible:

  • QVector sera renommé QList , vous perdez donc la stabilité de la référence lors de l'utilisation QList.
  • QVector (le nom) sera obsolète . QLinkedListsera supprimé.
  • QHash et QSet sont maintenant des tables de hachage à adressage ouvert, perdant également des garanties de stabilité de référence
  • QMap sera soutenu par std::map , éventuellement en changeant le comportement d'insertion et, pour QMultiMap, l'ordre des éléments équivalents.
  • Les tailles et index des conteneurs Qt deviendront qsizetype(plus ou moinsstd::ptrdiff_t ) (était:) int.

Donc, si vous voulez réécrire votre code utilisant des conteneurs, continuez avec les conteneurs Qt. Tout le monde bénéficie de décennies de stabilité avec les conteneurs STL.

Marc Mutz - mmutz
la source
3
Huh. J'avais l'impression que QList c'était l'équivalent de std::deque. De toute évidence, je n'aurais pas dû simplement parcourir la documentation.
Dennis Zickefoose
QVectora eu des crbeginamis depuis Qt 5.6
Bart Louwers
@Alex: d'accord, j'ai ajouté les plus faciles, mais tous les conteneurs Qt ne les ont pas encore (car vous n'utilisez pas std::reverse_iteratorles QHash/ QMapitérateurs cassés , qui, une fois déréférencés, reviennent à la mapped_typeplace de value_type). Rien qui ne peut être corrigé, mais voir mon EDIT de 2015.
Marc Mutz - mmutz
@ MarcMutz-mmutz Merci pour cette clarification.
Bart Louwers
1
Cela peut valoir la peine d'ajouter à la liste le fait que, par exemple, QVectorutilise intcomme index, limitant ainsi les tailles de 31 bits (même sur les systèmes 64 bits). De plus, il ne peut même pas stocker des INT_MAXéléments de taille supérieure à 1 octet. Par exemple, le plus grand que .size()je pouvais avoir QVector<float>sur gcc Linux x86_64 était de 536870907 éléments (2²⁹-5), tout en allouant std::vector<float>avec succès 4294967295 éléments (2³²-1; je n'ai pas essayé plus en raison du manque de RAM pour cela (cette taille prend déjà 16 Gio) ).
Ruslan
33

Décomposons ces affirmations en phénomènes réels mesurables:

  • Plus léger: les conteneurs Qt utilisent moins de mémoire que les conteneurs STL
  • Plus sûr: les conteneurs Qt ont moins de chances d'être mal utilisés
  • Plus facile: les conteneurs Qt présentent moins de charge intellectuelle

Plus facile

La revendication faite dans ce contexte est que l'itération de style Java est en quelque sorte "plus facile" que le style STL, et donc Qt est plus facile à utiliser grâce à cette interface supplémentaire.

Style Java:

QListIterator<QString> i(list);
while (i.hasNext())
    qDebug() << i.next();

Style STL:

QList<QString>::iterator i;
for (i = list.begin(); i != list.end(); ++i)
    qDebug << *i;

Le style d'itérateur Java a l'avantage d'être un peu plus petit et plus propre. Le problème est que ce n'est plus du style STL.

Style C ++ 11 STL

for( auto i = list.begin(); i != list.end(); ++i)
    qDebug << *i;

ou

C ++ 11 pour chaque style

for (QString i : list)
    qDebug << i;

Ce qui est tellement simple qu'il n'y a aucune raison d'utiliser quoi que ce soit d'autre (à moins que vous ne supportiez pas C ++ 11).

Mon préféré, cependant, est:

BOOST_FOREACH(QString i, list)
{
    qDebug << i;
}

Donc, comme on peut le voir, cette interface ne nous rapporte rien sauf une interface supplémentaire, en plus d'une interface déjà épurée, rationalisée et moderne. Ajouter un niveau d'abstraction inutile en plus d'une interface déjà stable et utilisable? Pas mon idée de «plus facile».

De plus, les interfaces Qt foreach et java ajoutent une surcharge; ils copient la structure et fournissent un niveau d'indirection inutile. Cela peut ne pas sembler beaucoup, mais pourquoi ajouter une couche de surcharge pour fournir une interface pas si simple? Java a cette interface car java n'a pas de surcharge d'opérateurs; C ++ le fait.

Plus sûr

La justification que Qt donne est le problème du partage implicite, qui n'est ni implicite ni un problème. Cela implique cependant un partage.

QVector<int> a, b;
a.resize(100000); // make a big vector filled with 0.

QVector<int>::iterator i = a.begin();
// WRONG way of using the iterator i:
b = a;
/*
Now we should be careful with iterator i since it will point to shared data
If we do *i = 4 then we would change the shared instance (both vectors)
The behavior differs from STL containers. Avoid doing such things in Qt.
*/

Premièrement, ce n'est pas implicite; vous attribuez explicitement un vecteur à un autre. La spécification de l'itérateur STL indique clairement que les itérateurs appartiennent au conteneur, nous avons donc clairement introduit un conteneur partagé entre b et a. Deuxièmement, ce n'est pas un problème; tant que toutes les règles de la spécification de l'itérateur sont respectées, absolument rien ne va mal. Le seul moment où quelque chose ne va pas, c'est ici:

b.clear(); // Now the iterator i is completely invalid.

Qt spécifie cela comme si cela signifiait quelque chose, comme un problème surgit de novo de ce scénario. Ce n'est pas le cas. L'itérateur est invalidé, et comme tout ce qui est accessible à partir de plusieurs zones disjointes, c'est ainsi que cela fonctionne. En fait, cela se produira facilement avec les itérateurs de style Java dans Qt, grâce à sa forte dépendance au partage implicite, qui est un anti-modèle comme documenté ici , et dans de nombreux autres domaines . Il semble particulièrement étrange que cette «optimisation» soit mise en œuvre dans un cadre évoluant de plus en plus vers le multithreading, mais c'est le marketing pour vous.

Plus léger

Celui-ci est un peu plus délicat. L'utilisation de stratégies de copie sur écriture et de partage implicite et de croissance rend très difficile la garantie de la quantité de mémoire utilisée par votre conteneur à un moment donné. Ceci est différent de la STL, qui vous donne de solides garanties algorithmiques.

Nous savons que la limite minimale de l'espace perdu pour un vecteur est la racine carrée de la longueur du vecteur , mais il ne semble y avoir aucun moyen d'implémenter cela dans Qt; les diverses "optimisations" prises en charge excluraient cette fonction très importante d'économie d'espace. La STL ne nécessite pas cette fonctionnalité (et la plupart utilisent une croissance doublée, ce qui représente plus de gaspillage), mais il est important de noter que vous pouvez au moins implémenter cette fonctionnalité, si nécessaire.

Il en va de même pour les listes à double chaînage, qui pourraient utiliser la liaison XOr pour réduire considérablement l'espace utilisé. Encore une fois, cela est impossible avec Qt, en raison de ses exigences de croissance et de COW.

COW peut en effet faire quelque chose de plus léger, mais les conteneurs intrusifs, tels que pris en charge par boost , et Qt les utilisaient fréquemment dans les versions précédentes, mais ils ne sont plus autant utilisés car ils sont difficiles à utiliser, dangereux et imposent un fardeau. sur le programmeur. COW est une solution beaucoup moins intrusive, mais peu attractive pour les raisons évoquées ci-dessus.

Il n'y a aucune raison pour que vous ne puissiez pas utiliser des conteneurs STL avec le même coût de mémoire ou moins que les conteneurs de Qt, avec l'avantage supplémentaire de savoir combien de mémoire vous gaspillerez à un moment donné. Il est malheureusement impossible de comparer les deux dans l'utilisation de la mémoire brute, car de tels benchmarks montreraient des résultats extrêmement différents dans différents cas d'utilisation, ce qui est le type exact de problème que la STL a été conçue pour corriger.

En conclusion

Évitez d'utiliser les conteneurs Qt lorsque cela est possible pour le faire sans imposer de coût de copie, et utilisez l'itération de type STL (peut-être via un wrapper ou la nouvelle syntaxe), dans la mesure du possible.

Alice
la source
4
Vos points sont largement valables, mais il y a des informations trompeuses là-dedans: Adding an unnecessary level of abstraction on top of an already stable and usable interface? Not my idea of "easier".les itérateurs de style Java de Qt n'ont pas été ajoutés à C ++ 11; ils sont antérieurs. Quoi qu'il en soit, Qt foreach(QString elem, list)est aussi simple que foreach ou BOOST_FOREACH de C ++ 11 et il fonctionne avec des compilateurs compatibles pré-C ++ 11.
weberc2
@ weberc2 Vous êtes confus; Les itérateurs de style Java de Qt sont ajoutés au-dessus des itérateurs C ++ (et non C ++ 11). C'est une couche supplémentaire d'abstraction (et inutile) qui gonfle l'interface, ce qui n'est pas plus facile. Et foreach pour Qt n'est pas aussi facile que BOOST_FOREACH, car il n'est notamment pas aussi sûr et n'a pas la même étendue de support (BOOST_FOREACH peut s'appliquer à n'importe quelle plage, pour n'importe quelle version de C ++, où comme foreach dans QT exige C + +03 conformité). Il faut éviter à tout prix le foreach de QT.
Alice
So, as we can see, this interface gains us nothing except an additional interface, *on top of* an already sleek, streamlined, and modern interface. Adding an unnecessary level of abstraction on top of an already stable and usable interface? Not my idea of "easier".(c'est moi qui souligne) Vous avez dit cela juste après nous avoir montré les versions C ++ 11 et BOOST de foreach, ce qui donne l'impression que la version Qt est construite à partir de l'un de ces deux, ce qui n'est pas le cas d'AFAICT. Je suis sûr que ce n'est pas ce que vous vouliez dire, mais c'est ainsi que ça se passe. D'où «informations trompeuses».
weberc2
1
Je dis simplement que vous êtes souvent très ambigu quant à la méthode d'itération dont vous parlez. Je crois que vous pensez que vous êtes clair et que votre langage est raisonnable, mais il semble étrange de refuser de préciser. D'accord pour ne pas être d'accord, je suppose.
weberc2
2
@Maximko c'est parce qu'ils utilisent l'idiome pimpl
Waqar
23

Conteneurs STL:

  • Avoir des garanties de performance
  • Peut être utilisé dans les algorithmes STL qui ont également des garanties de performance
  • Peut être exploité par des bibliothèques C ++ tierces telles que Boost
  • Sont des solutions standards et susceptibles de survivre aux solutions propriétaires
  • Encouragez la programmation générique des algorithmes et des structures de données. Si vous écrivez de nouveaux algorithmes et structures de données conformes à STL, vous pouvez tirer parti de ce que STL fournit déjà sans frais.
fbrereto
la source
6
Tout ce qui précède, sauf s'il s'agit d'un standard, est également vrai pour QTL, à condition que vous compiliez Qt avec le support STL (par défaut). Le support STL inclut les fonctions d'itérateur, les typedefs de conteneur (const_iterator, etc.), les fonctions de conversion (vers / depuis STL).
rpg
2
Qt n'est pas propriétaire
txwikinger
3
@rpg Presque toutes ne sont pas vraies pour QTL; QTL n'a pas de solides garanties de performances (car ils les ont facilement cassés dans le passé), ne sont pas conformes à la STL (pas d'inverse, et ne peuvent donc pas être utilisés par une grande partie de boost), ne sont pas standard (ils changent constamment entre les versions), et font n'encouragent pas la programmation générique (ils n'ont pas d'arguments de modèle pour les allocateurs, par exemple).
Alice
Cette réponse est pour la plupart obsolète et partiellement incorrecte.
Waqar le
15

Les conteneurs Qt utilisent un idiome de copie sur écriture.

TimW
la source
2
+1, pourrait être un avantage significatif en
termes de
33
Ou pourrait être un inconvénient majeur. Voir gotw.ca/publications/optimizations.htm
Kaz Dragon
3
Le refcount atomique semble plutôt bien se porter
rpg
Les conteneurs STL sont libres d'utiliser tous les idiomes existants tant qu'ils respectent leurs garanties de performances et les spécifications. COW est valide, même sous C ++ 11 / C ++ 14 STL.
Alice
1
@Alice COW n'est pas une implémentation valide la plupart du temps car elle brise la complexité du standard et les garanties de validité des itérateurs dans presque tous les cas. L'une des rares classes pouvant être implémentées avec COW était std::basic_stringet le standard a pris des mesures avec C ++ 11 pour rendre ce non-conforme.
Tiago Gomes
9

L'un des principaux problèmes est que l'API de Qt s'attend à ce que vous fournissiez des données dans les conteneurs de Qt, vous pouvez donc tout simplement utiliser les conteneurs Qt plutôt que de faire des allers-retours entre les deux.

De plus, si vous utilisez déjà les conteneurs Qt, il pourrait être légèrement plus optimal de les utiliser exclusivement, car vous n'auriez pas à inclure les fichiers d'en-tête STL et éventuellement à créer un lien dans les bibliothèques STL. Cependant, en fonction de votre chaîne d'outils, cela peut arriver de toute façon. Du point de vue du design, la cohérence est généralement une bonne chose.

qid
la source
1
La vitesse à laquelle vous devez "transformer en va-et-vient" entre les conteneurs STL et Qt dans une application réelle qui utilise STL sauf là où l'interfaçage avec Qt est généralement largement surestimée. La plupart du temps, vous effectuez des std :: transform venant de / vers la couche de présentation (qui utilise Qt) et vous obtenez le commutateur de conteneur gratuitement. Les parties intéressées peuvent accéder à projects.kde.org/projects/kde/kdepim/repository/revisions/… pour voir par elles-mêmes.
Marc Mutz - mmutz
8

Si les données avec lesquelles vous travaillez sont principalement utilisées pour piloter l'interface utilisateur basée sur Qt, utilisez définitivement les conteneurs Qt.

Si les données sont principalement utilisées en interne dans l'application et que vous ne risquez jamais de vous éloigner de Qt, à l'exception des problèmes de performances, utilisez les conteneurs Qt, car cela rendra les bits de données qui vont à l'interface utilisateur plus faciles à traiter.

Si les données sont principalement utilisées avec d'autres bibliothèques qui ne connaissent que les conteneurs STL, utilisez des conteneurs STL. Si vous rencontrez cette situation, vous avez des problèmes quoi qu'il arrive, car vous allez faire beaucoup de transferts entre les types de conteneurs, peu importe ce que vous faites.

Michael Kohne
la source
7

Outre la différence COW, les conteneurs STL sont beaucoup plus largement pris en charge sur une variété de plates-formes. Qt est suffisamment portable si vous limitez votre travail aux plates-formes "grand public", mais la STL est également disponible sur de nombreuses autres plates-formes plus obscures (par exemple, les DSP de Texas Instruments).

Parce que la STL est standard plutôt que contrôlée par une seule société, il y a, d'une manière générale, plus de programmeurs qui peuvent facilement lire, comprendre et modifier le code STL et plus de ressources (livres, forums en ligne, conférences, etc.) pour les soutenir dans faire cela qu'il n'y en a pour Qt. Cela ne veut pas dire que l'on devrait éviter Qt pour cette seule raison; juste cela, toutes choses étant égales par ailleurs, vous devriez utiliser par défaut la STL, mais bien sûr toutes choses sont rarement égales, vous devrez donc décider dans votre propre contexte ce qui a le plus de sens.

En ce qui concerne la réponse d'AlexKR: les performances de la STL sont garanties dans certaines limites, mais une implémentation donnée peut utiliser des détails dépendants de la plate-forme pour accélérer leur STL. Donc, dans ce sens, vous pouvez obtenir des résultats différents sur différentes plates-formes, mais cela ne sera jamais plus lent que la garantie explicite (bogues modulo).

métal
la source
9
En ce qui concerne votre premier point: je suppose que le PO fait référence à des projets qui utilisent déjà Qt, et qui sont donc déjà limités aux plates-formes «grand public». Il semble peu probable que quelqu'un utilise une bibliothèque aussi lourde que Qt uniquement pour ses classes de conteneurs.
ThisSuitIsBlackNot
4

Mes cinq cents: les conteneurs Qt sont censés fonctionner de la même manière sur différentes plates-formes. Alors que les conteneurs STL dépendent de l'implémentation STL. Vous pouvez obtenir des résultats de performances différents.

EDIT: Je ne dis pas que STL est "plus lent" mais je souligne les effets de divers détails d'implémentation.
Veuillez vérifier ceci , puis peut - être ceci .
Et ce n'est pas un vrai problème de STL. Évidemment, si vous avez une différence de performances significative, il y a un problème dans le code qui utilise STL.

alexkr
la source
Les conteneurs STL sont tous similaires, quelle que soit l'implémentation. Vous ne pouvez pas avoir un vecteur implémenté comme une liste dans les coulisses car il doit être dans un bloc de mémoire contigu. La STL est également généralement optimisée dans des proportions considérables sur toutes les principales plates-formes.
Yacoby
1
Si vous vous en tenez à ce que promet la STL (au lieu de supposer comment elle est implémentée), vous n'aurez jamais de problème à vous déplacer entre les plates-formes avec STL. Idem avec Qt.
Michael Kohne
C'est exactement le contraire de vrai. Les conteneurs STL fonctionnent toujours de la même manière sur toutes les plates-formes; s'ils ne le font pas, ils ne sont pas STL. QT, cependant, change radicalement les performances d'une version à l'autre, donc sur une plate-forme avec QT4.0 plutôt que QT4.8, vous pouvez obtenir de sérieux changements.
Alice
1
Vous confondez deux types de performances très différents; performances algorithmiques et performances de calcul pratiques. Toutes les implémentations STL garantissent les mêmes performances algorithmiques; si votre vecteur prend un temps de log (n) pour indexer un élément, ce n'est pas un vecteur STL. Vos liens pointent vers des performances de calcul pratiques, ce qui n'a aucun sens dans cette discussion; QT modifie ses algorithmes entre les versions et le même C ++ sur différentes plates-formes obtient des performances différentes. Celles-ci sont, d'après mon expérience, beaucoup plus malléables que les différences de performances STL.
Alice
3

Je suppose que cela dépend de la façon dont vous utilisez Qt. Si vous l'utilisez partout dans votre produit, il est probablement logique d'utiliser des conteneurs Qt. Si vous le contenez uniquement (par exemple) dans la partie de l'interface utilisateur, il peut être préférable d'utiliser des conteneurs standard C ++.

Nemanja Trifunovic
la source
3

Je suis d'avis que STL est un excellent logiciel, mais si je dois faire de la programmation liée à KDE ou à Qt, Qt est la voie à suivre. Cela dépend également du compilateur que vous utilisez, avec GCC STL fonctionne plutôt bien, mais si vous devez utiliser SUN Studio CC, STL vous causera probablement des maux de tête à cause du compilateur et non du STL en soi. Dans ce cas, puisque le compilateur vous fera mal à la tête, utilisez simplement Qt pour vous éviter les ennuis. Juste mes 2 cents ...

Paulo Lopes
la source
3

Il y a (parfois) une grande limitation dans QVector. Il ne peut allouer que des octets int de mémoire (notez que la limite est en octets et non en nombre d'éléments). Cela implique qu'essayer d'allouer des blocs contigus de mémoire plus grands que ~ 2 Go avec un QVector entraînera un crash. Cela se produit avec Qt 4 et 5. std :: vector n'a pas une telle limitation.

fedemp
la source
0

La principale raison d'utiliser les conteneurs STL pour moi est si vous avez besoin d'un allocateur personnalisé afin de réutiliser la mémoire dans de très gros conteneurs. Supposons par exemple que vous ayez un QMap qui stocke 1000000 entrées (paires clé / valeur). Dans Qt, cela implique exactement 1000000 millions d'allocations ( newappels) quoi qu'il arrive. Dans STL, vous pouvez toujours créer un allocateur personnalisé qui alloue en interne toute cette mémoire à la fois et l'affecte à chaque entrée au fur et à mesure que la carte est remplie.

Mon conseil est d'utiliser des conteneurs STL lors de l'écriture d'algorithmes critiques de performances dans la logique métier, puis de les reconvertir en conteneurs Qt lorsque les résultats sont prêts à être affichés par vos contrôles et formulaires d'interface utilisateur si nécessaire.

Darien Pardinas
la source
N'essayez pas de défendre le QTL ici, mais vous pouvez vous spécialiser QMapNode<K,V>pour le vôtre K, Vpour fournir le vôtre operator new.
Marc Mutz - mmutz