Kontenery STL czy Qt?

185

Jakie są zalety i wady korzystania z kontenerów Qt (QMap , QVectoritp) nad ich równowartości STL?

Widzę jeden powód, dla którego wolę Qt:

  • Kontenery Qt można przekazywać do innych części Qt. Na przykład można ich użyć do wypełnienia a, QVarianta następnie a QSettings(z pewnymi ograniczeniami akceptowane są tylko QListi QMap/ lub QHashktórych klucze są łańcuchami).

Czy jest jakiś inny?

Edycja : Zakładając, że aplikacja już opiera się na Qt.

Julien-L
źródło

Odpowiedzi:

135

Zacząłem od używania std::(w)stringwyłącznie kontenerów STL i konwersji do / z odpowiedników Qt, ale już przełączyłem się na QStringi stwierdzam, że coraz częściej używam kontenerów Qt.

Jeśli chodzi o ciągi, QStringoferuje znacznie bardziej kompletną funkcjonalność w porównaniu do std::basic_stringi jest całkowicie świadomy Unicode. Oferuje również wydajną implementację COW , na której w dużej mierze polegam.

Pojemniki Qt:

  • oferują tę samą implementację COW, co w QString, co jest niezwykle przydatne, jeśli chodzi o użycie foreachmakra Qt (które wykonuje kopię) oraz przy użyciu meta-typów lub sygnałów i gniazd.
  • może korzystać z iteratorów w stylu STL lub iteratorów w stylu Java
  • można przesyłać strumieniowo za pomocą QDataStream
  • są szeroko stosowane w API Qt
  • mieć stabilną implementację we wszystkich systemach operacyjnych. Implementacja STL musi być zgodna ze standardem C ++, ale poza tym jest wolna, jeśli chce (patrzstd::string kontrowersje COW). Niektóre implementacje STL są szczególnie złe.
  • udostępniaj skróty, które nie są dostępne, chyba że używasz TR1

QTL ma inną filozofię niż STL, którą dobrze podsumował J. Blanchette: „Podczas gdy kontenery STL są zoptymalizowane pod kątem surowej prędkości, klasy kontenerów Qt zostały starannie zaprojektowane, aby zapewnić wygodę, minimalne zużycie pamięci i minimalne rozszerzenie kodu”.
Powyższy link zawiera więcej szczegółów na temat implementacji QTL i zastosowanych optymalizacji.

rpg
źródło
12
W nowym standardzie c ++ 0x COW jest prawie poza stołem.
16
re: „starannie zaprojektowany, aby zapewnić [...] minimalne zużycie pamięci”. Nie powinieneś wierzyć marketingowi. Profil QList<double>w architekturze 32-bitowej do wykorzystania pamięci, aby przekonać się sam.
Marc Mutz - mmutz
11
„Oferuje również wydajną implementację COW”: COW nie jest tak wydajny, jeśli chodzi o aplikacje wielowątkowe ...
Grizzly
5
@ MarcMutz-mmutz spróbuj profilować QVectorzamiast QList. Istnieje dość wyjaśnienie Qt, że QList jest przeznaczony do przechowywania wskaźników na obiektach. Tak więc każdy podwójny element tworzony dynamicznie i wskaźnik do tego elementu jest przechowywany w QList. QList został zaprojektowany jako „środkowy” pojemnik między wektorem a połączoną listą. Nie jest przeznaczony do krytycznych przypadków związanych z pamięcią / wydajnością.
Dmitrij Sazonow
2
@ user1095108 Nie ma w tym nic złego. Idź użyć stl. Niektórzy z nas wolą szybko pisać poprawny kod. Nie ma w tym nic złego.
weberc2
178

To trudne pytanie. Może naprawdę sprowadzać się do filozoficznego / subiektywnego argumentu.

Biorąc to pod uwagę ...

Polecam zasadę „Będąc w Rzymie ... rób to, co Rzymianie”

Co oznacza, że ​​jeśli jesteś w krainie Qt, koduj tak jak Qt'ianie. Dotyczy to nie tylko kwestii czytelności / spójności. Zastanów się, co się stanie, jeśli przechowujesz wszystko w kontenerze STL, musisz przekazać wszystkie te dane do funkcji Qt. Czy naprawdę chcesz zarządzać pakietem kodu, który kopiuje rzeczy do / poza pojemniki Qt. Twój kod jest już mocno zależny od Qt, więc nie jest tak, że czynisz go bardziej „standardowym” za pomocą kontenerów stl. Jaki jest sens kontenera, jeśli za każdym razem, gdy chcesz go użyć do czegoś użytecznego, musisz skopiować go do odpowiedniego kontenera Qt?

Doug T.
źródło
1
+1 masz całkowitą rację, to właśnie starałem się wyjaśnić w moim pytaniu („Widzę jeden powód, aby preferować Qt”), więc nieco go zredagowałem. Dzięki
Julien-L,
Absolutnie dobrze powiedziane. Jeśli robisz QT, używaj rzeczy QT! Wyobraź sobie moment „WTF” dla opiekuna, gdy otwiera aplikację QT i widzi, że QT i STL są używane zamiennie. To może skończyć się (niepotrzebnym) koszmarem.
Wtorek
5
@ It'sPete STL jest częścią standardu; QT nie jest. Każdy kod korzystający ze standardu nigdy nie powinien wyzwalać momentu „WTF”.
Alice
6
Rzymianie wsadzili jeńców do Koloseum, a następnie upolowali ich za pomocą lwów. Jeśli wiesz lepiej, nie przestrzegaj lokalnych nawyków. Jest to tak samo prawdziwe w Qt, jak byłoby w przypadku współczesnego człowieka w Imperium Rzymskim ...
Marc Mutz - mmutz
1
@mmutz, mówisz, że to źle, chciałbym umieścić kod, który znalazłem w tym Koloseum i obejrzeć program
slf
65

Kontenery Qt są bardziej ograniczone niż kontenery STL. Kilka przykładów, w których STL są lepsze (wszystkie te trafiłem w przeszłości):

  • STL jest ustandaryzowany, nie zmienia się z każdą wersją Qt (Qt 2 miał QList(oparte na wskaźnikach) i QValueList(oparte na wartościach); Qt 3 miał QPtrListi QValueList; Qt 4 ma teraz QListi nie ma to jak QPtrList lub QValueList ).
    . Nawet jeśli kończy się przy użyciu Qt pojemników, należy użyć STL kompatybilne API podzbiór (tj push_back(), nie append(), front()niefirst() , ...), aby uniknąć przenoszenia ponownie Qt 5. Zarówno w Qt2-> 3, jak i Qt3-> 4 przejścia, zmiany w kontenerach Qt były jednymi z tych, które wymagały największej rezygnacji z kodu.
  • Wszystkie pojemniki dwukierunkowe STL mają rbegin()/rend() , dzięki czemu iteracja do tyłu jest symetryczna do iteracji do przodu. Nie wszystkie kontenery Qt mają je (nie mają ich asocjacyjne), więc odwrotna iteracja jest niepotrzebnie skomplikowana.
  • Kontenery STL mają insert()różne, ale kompatybilne typy iteratorów, przez co std::copy()znacznie rzadziej są potrzebne.
  • Kontenery STL mają Allocatorargument szablonu, dzięki czemu niestandardowe zarządzanie pamięcią jest banalne (wymagany typedef), w porównaniu z Qt ( QLineEditwymagane rozwidlenie s/QString/secqstring/). EDIT 20171220 : Zmniejsza to Qt postępów w projektowaniu alokatora zgodnie z C ++ 11 i C ++ 17, por. np. przemówienie Johna Lakosa ( część 2 ).
  • Nie ma odpowiednika Qt std::deque.
  • std::listma splice(). Ilekroć się używam std::list, to dlatego, że potrzebuję splice().
  • std::stack, std::queueWłaściwie agregowanie ich podstawową kontenera, a nie dziedziczą to, jak QStack, QQueuezrobić.
  • QSetjest jak std::unordered_set, nie jak std::set.
  • QListjest po prostu dziwne .

Wiele z powyższych problemów można rozwiązać dość łatwo w Qt , ale biblioteka kontenerów w Qt wydaje się w tej chwili odczuwać brak ukierunkowania na rozwój.

EDYCJA 20150106 : Po pewnym czasie próbowania wprowadzenia obsługi języka C ++ 11 do klas kontenerów Qt 5, zdecydowałem, że nie jest to warte pracy. Jeśli spojrzysz na pracę, która jest umieszczana w standardowej implementacji biblioteki C ++, jasne jest, że klasy Qt nigdy nie nadrobią zaległości. Wydaliśmyteraz Qt 5.4 iQVector nadal nie przenosimy elementów w trakcie realokacji, nie mamyemplace_back()lub nie warto się ...-push_back()Niedawno również odrzuciliśmyQOptionalszablon klasy, czekając na tostd::optional. Podobnie dlastd::unique_ptr. Mam nadzieję, że ten trend się utrzyma.

Marc Mutz - mmutz
źródło
3
Huh Byłem pod wrażeniem, QList był odpowiednikiem std::deque. Oczywiście nie powinienem po prostu przeglądać dokumentacji.
Dennis Zickefoose
QVectorma crbegini przyjaciół od Qt 5.6
Bart Louwers,
@Alex: racja, dodałem te łatwe, ale nie wszystkie jeszcze mają je w kontenerach Qt (ponieważ nie używasz std::reverse_iteratornad uszkodzonymi QHash/ QMapiteratorami, które po dereferencji zwracają mapped_typezamiast value_type). Nic nie może być ustalona, ale zobaczyć moją EDIT od 2015
Marc Mutz - mmutz
@ MarcMutz-mmutz Dziękujemy za wyjaśnienie.
Bart Louwers,
Warto dodać do listy fakt, że np. QVectorUżywa intjako indeksu, ograniczając w ten sposób 31-bitowe rozmiary (nawet w systemach 64-bitowych). Co więcej, nie może nawet przechowywać INT_MAXelementów o rozmiarze większym niż 1 bajt. Np. Największy, .size()jaki mogłem mieć QVector<float>na x86_64 Linux gcc, to 536870907 elementów (2²⁹-5), podczas gdy z std::vector<float>powodzeniem przydzielono 4294967295 elementów (2³²-1; nie próbowałem więcej z powodu braku pamięci RAM dla tego (ten rozmiar już zajmuje 16 GiB) ).
Ruslan
31

Podzielmy te twierdzenia na rzeczywiste mierzalne zjawiska:

  • Lżejsze: pojemniki Qt zużywają mniej pamięci niż pojemniki STL
  • Bezpieczniej: pojemniki Qt mają mniejszą szansę na niewłaściwe użycie
  • Łatwiej: pojemniki Qt stanowią mniejsze obciążenie intelektualne

Łatwiej

Twierdzi się w tym kontekście, że iteracja w stylu Java jest w jakiś sposób „łatwiejsza” niż styl STL, a zatem Qt jest łatwiejszy w użyciu z powodu tego dodatkowego interfejsu.

Styl Java:

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

Styl STL:

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

Styl iteratora Java ma tę zaletę, że jest nieco mniejszy i bardziej przejrzysty. Problem polega na tym, że tak naprawdę nie jest to już styl STL.

Styl C ++ 11 STL

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

lub

Styl foreach C ++ 11

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

Co jest tak drastycznie proste, że nie ma powodu, aby używać czegoś innego (chyba że nie obsługujesz C ++ 11).

Moim ulubionym jest jednak:

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

Tak więc, jak widzimy, ten interfejs nie daje nam nic poza dodatkowym interfejsem, na dodatek do już eleganckiego, usprawnionego i nowoczesnego interfejsu. Dodanie niepotrzebnego poziomu abstrakcji na już stabilnym i użytecznym interfejsie? Nie mój pomysł na „łatwiej”.

Ponadto interfejsy foret i java Qt zwiększają koszty; kopiują strukturę i zapewniają niepotrzebny poziom pośredni. Może to nie wydawać się dużo, ale po co dodawać warstwę kosztów ogólnych, aby zapewnić niezbyt prostszy interfejs? Java ma ten interfejs, ponieważ java nie ma przeciążenia operatora; C ++ tak.

Bezpieczniej

Uzasadnieniem, które podaje Qt, jest niejawny problem z udostępnianiem, który nie jest ani niejawny, ani stanowi problem. Wymaga to jednak udostępniania.

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.
*/

Po pierwsze, nie jest to dorozumiane; wyraźnie przypisujesz jeden wektor do drugiego. Specyfikacja iteratora STL wyraźnie wskazuje, że iteratory należą do kontenera, więc wyraźnie wprowadziliśmy wspólny kontener między b i a. Po drugie, to nie jest problem; tak długo, jak przestrzegane są wszystkie reguły specyfikacji iteratora, absolutnie nic nie pójdzie źle. Jedyny raz coś poszło nie tak:

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

Qt określa to tak, jakby to coś znaczyło, tak jak problem powstaje de novo w tym scenariuszu. Tak nie jest. Iterator jest unieważniony i tak jak wszystko, co jest dostępne z wielu rozłącznych obszarów, tak właśnie działa. W rzeczywistości stanie się to łatwo z iteratorami stylu Java w Qt, dzięki silnemu poleganiu na niejawnym współużytkowaniu, co jest antypatternem opisanym tutaj i na wielu innych obszarach . Wydaje się szczególnie dziwne, że ta „optymalizacja” jest stosowana w ramach, które coraz bardziej zbliżają się do wielowątkowości, ale to dla ciebie marketing.

Zapalniczka

Ten jest nieco trudniejszy. Korzystanie ze strategii kopiowania przy zapisie oraz niejawnego udostępniania i wzrostu powoduje, że bardzo trudno jest zagwarantować, ile pamięci zużyje Twój kontener w danym momencie. W przeciwieństwie do STL, który daje silne gwarancje algorytmiczne.

Wiemy, że minimalną granicą zmarnowanego miejsca dla wektora jest pierwiastek kwadratowy z długości wektora , ale wydaje się, że nie ma możliwości zaimplementowania tego w Qt; różne obsługiwane przez nich „optymalizacje” wykluczałyby tę bardzo ważną funkcję oszczędzania miejsca. STL nie wymaga tej funkcji (i większość korzysta z podwójnego wzrostu, co jest bardziej marnotrawstwem), ale ważne jest, aby pamiętać, że możesz przynajmniej zaimplementować tę funkcję, jeśli zajdzie taka potrzeba.

To samo dotyczy podwójnie połączonych list, które mogłyby użyć linkowania XOr, aby drastycznie zmniejszyć zużycie miejsca. Ponownie, jest to niemożliwe w przypadku Qt, ze względu na jego wymagania dotyczące wzrostu i COW.

COW może rzeczywiście uczynić coś lżejszym, ale również pojemniki Intrusive, takie jak obsługiwane przez boost , i Qt często ich używały we wcześniejszych wersjach, ale nie są już używane tak często, ponieważ są trudne w użyciu, niebezpieczne i nakładają obciążenie na programatorze. COW jest znacznie mniej inwazyjnym rozwiązaniem, ale nieatrakcyjnym z powyższych powodów.

Nie ma powodu, dla którego nie można było używać kontenerów STL o takim samym koszcie pamięci lub mniejszym niż pojemniki Qt, a dodatkową korzyścią jest faktyczna wiedza o ilości pamięci, którą można zmarnować w danym momencie. Nie da się niestety porównać tych dwóch pod względem wykorzystania pamięci surowej, ponieważ takie testy porównawcze pokazałyby bardzo różne wyniki w różnych przypadkach użycia, co jest dokładnym rodzajem problemu, który STL miał rozwiązać.

Podsumowując

Unikaj korzystania z kontenerów Qt, gdy jest to możliwe, bez nakładania kosztów kopiowania i, w miarę możliwości, używaj iteracji typu STL (być może poprzez opakowanie lub nową składnię).

Alice
źródło
4
Twoje punkty są w dużej mierze poprawne, ale są tam pewne wprowadzające w błąd informacje: Adding an unnecessary level of abstraction on top of an already stable and usable interface? Not my idea of "easier".iteratory w stylu Java Qt nie zostały dodane do C ++ 11; wyprzedzają to. W każdym razie Qt foreach(QString elem, list)jest tak samo łatwe jak foreach C ++ 11 lub BOOST_FOREACH i działa z kompilatorami zgodnymi z wcześniejszymi wersjami C ++ 11.
weberc2
@ weberc2 Jesteś zdezorientowany; Iteratory stylu Java Qt są dodawane do iteratorów C ++ (nie C ++ 11). Jest to dodatkowa warstwa abstrakcji (i niepotrzebna), która przesadza interfejs, co nie jest łatwiejsze. I Foreach dla Qt nie jest tak łatwe, jak BOOST_FOREACH, ponieważ nie jest tak bezpieczne i nie ma takiej samej szerokości wsparcia (BOOST_FOREACH może mieć zastosowanie do dowolnego zakresu, dla dowolnej wersji C ++, gdzie tak jak Foreach w QT wymaga C + Zgodność +03). Za wszelką cenę należy unikać foreach 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".(moje podkreślenie) Powiedziałeś to zaraz po tym, jak pokazałeś nam wersje Foreach C ++ 11 i BOOST, dzięki czemu brzmi to tak, jakby wersja Qt była zbudowana z jednego z tych dwóch, co nie jest przypadkiem AFAICT. Jestem pewien, że nie o to ci chodziło, ale tak to wychodzi. Stąd „informacje wprowadzające w błąd”.
weberc2
It's an additional layer of abstraction (and an unnecessary one) that bloats the interface, which is not easier.Nadal nie jest jasne, z czym się porównujesz. Iteratory C ++ 03? Iteratory C ++ 11? BOOST_FOREACH? Wszystkie powyższe?
weberc2
1
Mówię tylko, że często jesteś bardzo niejednoznaczny, do której metody iteracji się odwołujesz. Uważam, że uważasz, że jesteś czysty i że twój język jest rozsądny, ale odmawianie podania szczegółów wydaje się dziwne. Zgadzam się nie zgadzać, tak sądzę.
weberc2
23

Kontenery STL:

  • Posiadaj gwarancje wydajności
  • Może być stosowany w algorytmach STL, które mają również gwarancje wydajności
  • Może być wykorzystany przez zewnętrzne biblioteki C ++, takie jak Boost
  • Są standardowe i prawdopodobnie przeżyją autorskie rozwiązania
  • Zachęcaj do ogólnego programowania algorytmów i struktur danych. Jeśli napiszesz nowe algorytmy i struktury danych zgodne ze STL, możesz wykorzystać to, co STL już zapewnia bez żadnych kosztów.
fbrereto
źródło
5
Wszystkie powyższe elementy oprócz tego, że są standardem, są prawdziwe również dla QTL, pod warunkiem, że kompilujesz Qt z obsługą STL (domyślnie). Obsługa STL obejmuje funkcje iteratora, typedefs kontenera (const_iterator itp.), Funkcje konwersji (do / z STL).
rpg
2
Qt nie jest zastrzeżony
txwikinger
3
@rpg Prawie wszystkie z nich nie są zgodne z QTL; QTL nie ma silnych gwarancji wydajności (ponieważ łatwo je zepsuły w przeszłości), nie są zgodne z STL (brak rewersu, a zatem nie może być używany przez znaczną poprawę), nie są standardowe (zmieniają się stale między wersjami) i robią nie zachęcają do programowania ogólnego (nie mają na przykład argumentów szablonów dla alokatorów).
Alice
15

Kontenery Qt używają idiomu „kopiuj przy zapisie”.

TimW
źródło
2
+1, może być znaczącą przewagą w wydajności i zasobach
RedGlyph
32
Lub może być znaczną wadą. Zobacz gotw.ca/publications/optimizations.htm
Kaz Dragon
3
Rachunek
rpg
Kontenery STL mogą używać dowolnych idiomów, o ile spełniają one swoje gwarancje wydajności i specyfikację. COW jest ważny, nawet w C ++ 11 / C ++ 14 STL.
Alice
1
@Alice COW przez większość czasu nie jest prawidłową implementacją, ponieważ łamie złożoność standardu i gwarantuje poprawność iteratora w prawie każdym przypadku. Jedną z niewielu klas, które można zaimplementować za pomocą COW, była std::basic_stringnorma, która podjęła działania w C ++ 11, aby uczynić to niezgodnym.
Tiago Gomes
9

Jednym z głównych problemów jest to, że API Qt oczekuje, że dostarczysz dane do kontenerów Qt, więc możesz po prostu użyć kontenerów Qt zamiast przekształcać się w obie strony.

Ponadto, jeśli już korzystasz z kontenerów Qt, może być nieco bardziej optymalne używanie ich wyłącznie, ponieważ nie musisz dołączać plików nagłówkowych STL i potencjalnie linkować do bibliotek STL. Jednak w zależności od zestawu narzędzi może się to zdarzyć. Z perspektywy projektowania spójność jest ogólnie dobrą rzeczą.

qid
źródło
1
Szybkość, z jaką musisz „przekształcać się do przodu i do tyłu” między kontenerami STL i Qt w prawdziwej aplikacji, która korzysta z STL, z wyjątkiem sytuacji, gdy interfejs z Qt jest zasadniczo znacznie zawyżony. Przez większość czasu robisz std :: transform przechodząc do / z warstwy prezentacji (która używa Qt) i dostajesz przełącznik kontenera za darmo. Zainteresowane strony mogą przeglądać strony projects.kde.org/projects/kde/kdepim/repository/revisions/…, aby zobaczyć na własne oczy.
Marc Mutz - mmutz
8

Jeśli dane, z którymi pracujesz, służą głównie do obsługi interfejsu użytkownika opartego na Qt, zdecydowanie użyj kontenerów Qt.

Jeśli dane są najczęściej używane wewnętrznie w aplikacji i nigdy nie będziesz mógł przenosić się z Qt, a następnie pomijając problemy z wydajnością, użyj kontenerów Qt, ponieważ ułatwi to radzenie sobie z częściami danych, które trafiają do interfejsu użytkownika.

Jeśli dane są używane głównie w połączeniu z innymi bibliotekami, które wiedzą tylko o kontenerach STL, użyj kontenerów STL. Jeśli masz taką sytuację, masz kłopoty bez względu na wszystko, ponieważ będziesz musiał dużo przenosić pomiędzy typami kontenerów, bez względu na to, co robisz.

Michael Kohne
źródło
7

Oprócz różnicy COW, kontenery STL są znacznie szerzej obsługiwane na różnych platformach. Qt jest wystarczająco przenośny, jeśli ograniczysz swoją pracę do platform „głównego nurtu”, ale STL jest dostępny również na wielu innych, bardziej niejasnych platformach (np. DSP Texas Instruments).

Ponieważ STL jest standardem, a nie kontrolowaną przez jedną korporację, ogólnie rzecz biorąc, jest więcej programistów, którzy mogą łatwo czytać, rozumieć i modyfikować kod STL oraz więcej zasobów (książek, forów internetowych, konferencji itp.), Aby wspierać je w robiąc to niż w przypadku Qt. Nie oznacza to, że należy unikać Qt tylko z tego powodu; po prostu, wszystkie inne rzeczy są równe, powinieneś domyślnie korzystać z STL, ale oczywiście wszystkie rzeczy są rzadko równe, więc będziesz musiał zdecydować w swoim własnym kontekście, który jest najbardziej sensowny.

W odniesieniu do odpowiedzi AlexKR: wydajność STL jest gwarantowana w określonych granicach, ale dana implementacja może wykorzystywać szczegóły zależne od platformy w celu przyspieszenia ich STL. W tym sensie możesz uzyskiwać różne wyniki na różnych platformach, ale nigdy nie będzie to wolniejsze niż wyraźna gwarancja (błędy modulo).

metal
źródło
9
W odniesieniu do pierwszej kwestii: zakładam, że PO odnosi się do projektów, które już korzystają z Qt, a zatem są już ograniczone do platform „głównego nurtu”. Wydaje się mało prawdopodobne, aby ktoś wciągnął tak ciężką bibliotekę jak Qt tylko dla swoich klas kontenerów.
ThisSuitIsBlackNot
4

Moje pięć centów: kontenery Qt powinny działać podobnie na różnych platformach. Podczas gdy kontenery STL zależą od implementacji STL. Możesz uzyskać różne wyniki wydajności.

EDYCJA: Nie mówię, że STL jest „wolniejszy”, ale wskazuję na efekty różnych szczegółów implementacji.
Sprawdź to , a potem może to .
I to nie jest prawdziwy problem STL. Oczywiście, jeśli masz znaczną różnicę w wydajności, to jest problem w kodzie, który używa STL.

alexkr
źródło
Wszystkie kontenery STL są podobne, niezależnie od implementacji. Nie można zaimplementować wektora za listą za kulisami, ponieważ musi on znajdować się w ciągłym bloku pamięci. STL jest zwykle zoptymalizowany w ogromnym stopniu na wszystkich głównych platformach.
Yacoby
1
Jeśli będziesz trzymać się tego, co obiecuje STL (zamiast zakładać, jak to jest zaimplementowane), nigdy nie będziesz mieć problemu z przemieszczaniem się między platformami z STL. To samo z Qt.
Michael Kohne,
To jest dokładne przeciwieństwo prawdy. Kontenery STL zawsze działają tak samo na wszystkich platformach; jeśli nie, to nie są STL. Jednak QT drastycznie zmienia wydajność z wersji na wersję, więc na platformie z QT4.0 zamiast QT4.8 można wprowadzić poważne zmiany.
Alice
1
Mylisz dwa bardzo różne rodzaje wydajności; wydajność algorytmiczna i praktyczna wydajność obliczeniowa. Wszystkie implementacje STL gwarantują taką samą wydajność algorytmiczną; jeśli twój wektor zajmuje log (n) czas na indeksowanie elementu, nie jest to wektor STL. Twoje linki wskazują na praktyczną wydajność obliczeniową, co nie ma znaczenia w tej dyskusji; QT zmienia swoje algorytmy między wersjami, a ten sam C ++ na różnych platformach uzyskuje inną wydajność. Z mojego doświadczenia są one znacznie bardziej plastyczne niż różnice w wydajności STL.
Alice
3

Myślę, że to zależy od sposobu, w jaki używasz Qt. Jeśli używasz go w całym swoim produkcie, prawdopodobnie lepiej jest używać pojemników Qt. Jeśli zawiera się go tylko (na przykład) część interfejsu użytkownika, może być lepiej użyć standardowych kontenerów C ++.

Nemanja Trifunovic
źródło
3

Uważam, że STL jest doskonałym oprogramowaniem, ale jeśli mam zrobić programowanie związane z KDE lub Qt, to Qt jest właściwą drogą. Zależy to również od używanego kompilatora, z GCC STL działa całkiem dobrze, jednak jeśli musisz użyć powiedz SUN Studio CC, wówczas STL najprawdopodobniej sprawi ci ból głowy z powodu kompilatora, a nie STL per se. W takim przypadku, ponieważ kompilator sprawi ci ból głowy, po prostu użyj Qt, aby zaoszczędzić ci kłopotów. Tylko moje 2 centy ...

Paulo Lopes
źródło
3

QVector ma (czasem) duże ograniczenie. Może alokować tylko int bajtów pamięci (pamiętaj, że limit jest w bajtach, a nie w liczbie elementów). Oznacza to, że próba przydzielenia ciągłych bloków pamięci większych niż ~ 2 GB za pomocą QVectora spowoduje awarię. Dzieje się tak z Qt 4 i 5. std :: vector nie ma takich ograniczeń.

fedemp
źródło
0

Dla mnie głównym powodem korzystania z kontenerów STL jest to, że potrzebujesz niestandardowego programu przydzielającego, aby ponownie wykorzystać pamięć w bardzo dużych kontenerach. Załóżmy na przykład, że masz QMap, która przechowuje 1000000 pozycji (pary klucz / wartość). W Qt oznacza to dokładnie 1000000 milionów alokacji (new połączeń) bez względu na wszystko. W STL zawsze możesz utworzyć niestandardowy alokator, który wewnętrznie przydziela całą tę pamięć jednocześnie i przypisuje ją do każdego wpisu, gdy mapa jest zapełniona.

Radzę korzystać z kontenerów STL podczas pisania algorytmów krytycznych pod względem wydajności w logice biznesowej, a następnie przekonwertować je z powrotem na kontenery Qt, gdy wyniki będą gotowe, wyświetlając je za pomocą formantów interfejsu użytkownika i formularzy w razie potrzeby.

Darien Pardinas
źródło
Nie próbuje bronić QTL tutaj, ale mogłaby specjalizować QMapNode<K,V>dla twojego K, Vaby zapewnić swoim własnym operator new.
Marc Mutz - mmutz