STL або Qt контейнери?


185

Які плюси і мінуси використання Qt контейнерів ( QMap, QVectorі т.д.) над їх STL еквівалент?

Я бачу одну причину віддати перевагу Qt:

  • Контейнери Qt можуть передаватися в інші частини Qt. Наприклад, їх можна використовувати для заповнення a, QVariantа потім a QSettings(але з деяким обмеженням, приймаються лише QListта QMap/ QHashчиї ключі є рядками).

Чи є ще якісь?

Редагувати : якщо припускати, що програма вже покладається на Qt.

Відповіді:


135

Я почав використовувати std::(w)stringвиключно контейнери STL та перетворювати на / з еквівалентів Qt, але я вже перейшов на QStringта виявляю, що я використовую контейнери Qt все більше і більше.

Що стосується рядків, він QStringпропонує набагато більш повний функціонал порівняно з цим, std::basic_stringі це повністю відомо Unicode. Він також пропонує ефективну реалізацію COW , на яку я став сильно покладатися.

Контейнери Qt:

  • пропонують таку ж реалізацію COW, як і в QString, що надзвичайно корисно, якщо мова йде про використання foreachмакросу Qt (який робить копію) та при використанні мета-типів або сигналів та слотів.
  • можна використовувати ітератори стилю STL або ітератори стилю Java
  • є потоковими QDataStream
  • широко використовуються в API Qt
  • мають стабільну реалізацію в операційних системах. Реалізація STL повинна відповідати стандарту C ++, але інакше вільна робити, як заманеться (дивstd::string Суперечку COW). Деякі реалізації STL особливо погані.
  • надайте хеші, які недоступні, якщо ви не використовуєте TR1

QTL має іншу філософію від STL, яку добре узагальнив Дж. Бланшетте: "Якщо контейнери STL оптимізовані для швидкої необмеженої швидкості, класи контейнерів Qt були ретельно розроблені для забезпечення зручності, мінімального використання пам'яті та мінімального розширення коду."
Наведене вище посилання містить більш детальну інформацію про реалізацію QTL та які оптимізації використовуються.


12
У новому стандарті c ++ 0x COW майже не вдається.

16
re: "ретельно розроблений для забезпечення [...] мінімального використання пам'яті". Ви не повинні вірити маркетингу. Профіль QList<double>32-розрядної архітектури для використання пам'яті, щоб переконатися в цьому.
Марк Муц - mmutz

11
"Він також пропонує ефективну реалізацію COW": COW не все так ефективно, коли мова йде про багатопотокові програми ...
Grizzly

5
@ MarcMutz-mmutz спробуйте профіль QVectorзамість QList. Є досить пояснення Qt, що QList призначений для зберігання покажчиків на об'єкти. Отже кожен подвійний елемент, створений динамічно, і вказівник на цей елемент зберігається QList. QList розроблений як "середній" контейнер між вектором та пов'язаним списком. Він не розроблений для критичних випадків пам'яті / продуктивності.
Дмитро Сазонов

2
@ user1095108 У цьому немає нічого поганого. Перейдіть на використання стл. Деякі з нас вважають за краще швидко написати правильний код. З цим теж немає нічого поганого.
weberc2

178

Це важко відповісти на питання. Це дійсно може звестись до філософського / суб'єктивного аргументу.

Це сумно...

Я рекомендую правило "Коли в Римі ... роби так, як роблять римляни"

Що означає, якщо ви перебуваєте в землі Qt, кодуйте як Qt'ians. Це стосується не лише проблем читання / послідовності. Поміркуйте, що станеться, якщо ви зберігаєте все в контейнері stl, тоді вам доведеться передати всі ці дані у функцію Qt. Ви дійсно хочете керувати купою коду, який копіює речі в контейнери Qt або з них. Ваш код вже сильно залежить від Qt, тому його не так, як ви робите його "стандартним", використовуючи контейнери stl. І в чому сенс контейнера, якщо кожного разу, коли ви хочете використовувати його для чогось корисного, потрібно копіювати його у відповідний контейнер Qt?


1
+1 ви абсолютно праві, це те, що я намагався пояснити у своєму питанні ("я бачу одну причину, щоб віддати перевагу Qt"), тому я трохи відредагував це. Спасибі
Жульєн-Л

Абсолютно добре сказано. Якщо ви робите QT, використовуйте QT! Уявіть момент "WTF" для обслуговуючого персоналу, коли він відкриває програму QT і бачить, як QT та STL використовуються взаємозамінно. Це може закінчитися «непотрібним» кошмаром.
ЦеПет

5
@ ItPete STL є частиною стандарту; QT - ні. Будь-який код, який використовує стандарт, ніколи не повинен викликати "WTF" момент.
Аліса

6
Римляни посадили своїх полонених у Колізей, а потім полювали на них левами. Якщо ви знаєте краще, не дотримуйтесь місцевих звичок. Це так само правда в Qt, як це було б для сучасної людини в Римській імперії ...
Марк Муц - mmutz

1
@mmutz ви кажете, що як це погано, я хотів би покласти якийсь код, який я знайшов у тому Колізеї, і подивитися шоу
slf

65

Контейнери Qt більш обмежені, ніж контейнери STL. Кілька прикладів того, де STL є вищими (усе це я потрапив у минулому):

  • STL стандартизований, не змінюється з кожною версією Qt (Qt 2 мав QList(на основі покажчика) та QValueList(на основі значення); Qt 3 мав QPtrListі QValueList; Qt 4 зараз має QList, і це зовсім не так, як QPtrList або QValueList ).
    Навіть якщо ви використовуєте контейнери Qt, використовуйте підмножину API-сумісного STL (тобто push_back(), не append();, front()ніfirst() , ...), щоб уникнути переносу ще раз Qt 5. І в Qt2-> 3 і Qt3-> 4 Переходи, зміни контейнерів Qt були одними з тих, що потребують найбільшої зміни коду.
  • Усі двонаправлені контейнери STL мають rbegin()/rend() , що робить зворотну ітерацію симетричною для ітерації вперед. Не всі контейнери Qt мають їх (асоціативні - ні), тому зворотна ітерація зайво складна.
  • Контейнери STL мають insert()різноманітний тип, але сумісний, ітератор, що робить std::copy()набагато рідше необхідним.
  • Контейнери STL мають Allocatorаргумент шаблону, що робить користувальницьке управління пам'яттю тривіальним (потрібен typedef), порівняно з Qt (форк, QLineEditнеобхідний для s/QString/secqstring/). EDIT 20171220 : Це скорочує Qt авансів у дизайні розподільника відповідно до C ++ 11 та C ++ 17, пор. наприклад , розмова Джона Лакоса ( частина 2 ).
  • Не існує еквівалента Qt std::deque.
  • std::listмає splice(). Щоразу, коли я опиняюсь, що я використовую std::list, це тому, що мені потрібно splice().
  • std::stack, std::queueНалежним чином агрегувати їх основний контейнер, і не успадковується нею, як QStack, QQueueробити.
  • QSetце як std::unordered_set, а не як std::set.
  • QListце просто дивно .

Багато з перерахованого вище можна було вирішити досить легко в Qt , але схоже, що бібліотека контейнерів у Qt наразі відчуває недостатню спрямованість на розробку.

EDIT 20150106 : Провівши деякий час, намагаючись залучити підтримку C ++ 11 до класів контейнерів Qt 5, я вирішив, що працювати не варто. Якщо ви подивитеся на роботу, яка вкладається у стандартні впровадження бібліотеки C ++, то цілком зрозуміло, що класи Qt ніколи не наздоганяють. Ми випустили Qt 5.4 зараз іQVector досі не переміщуємо елементи на перерозподіл, не маєemplace_back()або не оцінюєpush_back()... Ми також нещодавно відхилилиQOptionalшаблон класу, чекаючиstd::optionalнатомість. Так само і дляstd::unique_ptr. Я сподіваюся, що ця тенденція продовжується.


3
Ага. У мене під враженням QList було рівнозначно std::deque. Ясна річ, я не повинен був просто зняти документацію.
Денніс Зіккефуз

QVectorмав crbeginі друзів з Qt 5.6
Bart Louwers

@Alex: правда, я додав найпростіші, але не у всіх контейнерах Qt є (проте ви не користуєтесь std::reverse_iteratorполаманими QHash/ QMapітераторами, які при дереференції повертаються mapped_typeзамість них value_type). Нічого такого , що не може бути виправлено, але бачити мою EDIT від 2015.
Marc Mutz - mmutz

@ MarcMutz-mmutz Дякую за уточнення.
Барт Луверс

Можливо, варто додати до списку той факт, що, наприклад, QVectorвикористовує intв якості свого індексу, обмежуючи таким чином 31-бітові розміри (навіть у 64-бітних системах). Більше того, він навіть не може зберігати INT_MAXелементи розміром більше 1 байта. Наприклад, найбільший, який .size()я міг мати QVector<float>на x86_64 Linux gcc, був 536870907 елементів (2²⁹-5), а std::vector<float>успішно виділив 4294967295 елементів (2³²-1; не намагався більше через відсутність оперативної пам’яті для цього (цей розмір займає вже 16 ГБ) ).
Руслан

31

Розбимо ці твердження на фактичні вимірювані явища:

  • Запальничка: контейнери Qt використовують менше пам'яті, ніж контейнери STL
  • Безпечніше: контейнери Qt мають менше можливостей неправильного використання
  • Простіше: контейнери Qt представляють менший інтелектуальний тягар

Легше

Ствердження, висловлене в цьому контексті, полягає в тому, що ітерація в стилі java якимось чином "простіша", ніж стиль STL, і тому Qt легше використовувати через цей додатковий інтерфейс.

Стиль Java:

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

Стиль STL:

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

Стиль ітератора Java має перевагу в тому, що він трохи менший і чистіший. Проблема в тому, що це насправді вже не стиль STL.

C ++ 11 STL Стиль

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

або

C ++ 11 стиль передбачення

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

Що настільки різко просто, що немає жодного приводу використовувати будь-що інше (якщо ви не підтримуєте C ++ 11).

Мій улюблений, однак, такий:

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

Отже, як ми бачимо, цей інтерфейс не отримує від нас нічого, крім додаткового інтерфейсу, окрім уже гладкого, обтічного та сучасного інтерфейсу. Додавання зайвого рівня абстракції поверх уже стабільного та зручного інтерфейсу? Не моя думка про "легше".

Також інтерфейси Qt foreach та java додають накладні витрати; вони копіюють структуру і забезпечують непотрібний рівень непрямості. Це може здатися не дуже схожим, але навіщо додавати шар накладних витрат, щоб забезпечити не такий вже й простіший інтерфейс? У Java є цей інтерфейс, оскільки java не має перевантаження оператора; C ++ робить.

Безпечніше

Обґрунтуванням, яке дає Qt, є неявна проблема спільного використання, яка не є ні неявною, ні проблемою. Однак це передбачає обмін.

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

По-перше, це не неявно; ви явно присвоюєте один вектор іншому. Специфікація ітератора STL чітко вказує, що ітератори належать до контейнера, тому ми чітко ввели спільний контейнер між b і a. По-друге, це не проблема; доки будуть дотримані всі правила специфікації ітератора, абсолютно нічого не піде не так. Єдиний раз, коли щось піде не так:

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

Qt вказує це так, ніби це щось означає, на зразок проблеми виникає de novo з цього сценарію. Це не так. Ітератор недійсний, і як і все, до чого можна дістатися з декількох непересічних областей, саме так він працює. Насправді це легко відбудеться з ітераторами стилів Java в Qt, завдяки тому, що вони сильно залежать від неявного обміну, що є антипатерном, як це зафіксовано тут , і в багатьох інших областях . Особливо дивно здається, що ця "оптимізація" може бути використана в рамках, що все більше спрямовується на багатопотоковість, але це маркетинг для вас.

Легше

Цей трохи складніше. Використання стратегій "Копіювати на запис" та "Неявне поділення та зростання" дуже ускладнює фактичні гарантії щодо обсягу пам'яті, яку використовує ваш контейнер у будь-який момент часу. Це на відміну від STL, який дає чіткі алгоритмічні гарантії.

Ми знаємо, що мінімальна межа витраченого простору для вектора - це квадратний корінь довжини вектора , але, мабуть, немає можливості реалізувати це в Qt; різноманітні «оптимізації», які вони підтримують, виключають цю дуже важливу функцію економії місця. Ця STL не вимагає цієї функції (і більшість використовує подвоєний ріст, який є більш марним), але важливо зазначити, що ви могли принаймні реалізувати цю функцію, якщо це буде потрібно.

Те саме стосується подвійно пов'язаних списків, які могли використовувати посилання XOr для різкого скорочення використовуваного простору. Знову ж таки, це неможливо з Qt, оскільки це вимагає зростання та переробки COW.

COW дійсно може зробити щось легше, але це може зробити нав'язливі контейнери, такі як підтримка boost , і Qt використовували їх часто в попередніх версіях, але вони більше не використовуються, оскільки вони важкі у використанні, небезпечні та накладають тягар. на програміста. COW - набагато менш нав'язливе рішення, але непривабливе з причин, викладених вище.

Немає жодної причини, чому ви не могли б використовувати контейнери STL з такою самою вартістю пам'яті або меншою, ніж контейнери Qt, з додатковою перевагою фактично знати, скільки пам’яті ви будете витрачати в будь-який момент часу. На жаль, неможливо порівняти ці два у використанні необробленої пам’яті, оскільки такі орієнтири показали б диво різні результати в різних випадках використання, що є саме тим видом проблеми, який було призначено для виправлення STL.

У висновку

Уникайте використання контейнерів Qt, коли це можливо, без накладення вартості копіювання, і використовуйте ітерацію типу STL (можливо, за допомогою обгортки або нового синтаксису), коли це можливо.


4
Ваші бали значною мірою справедливі, але тут є деяка оманлива інформація: Adding an unnecessary level of abstraction on top of an already stable and usable interface? Not my idea of "easier".ітератори стилю Java на Qt не були додані на C ++ 11; вони передували цьому. У будь-якому випадку Qt foreach(QString elem, list)так само простий, як і передбачення C ++ 11 або BOOST_FOREACH, і він працює з компіляторами, що відповідають стандартам pre-C ++ 11.
weberc2

@ weberc2 Ви заплутані; Ітератори стилю Java Qt додаються поверх ітераторів C ++ (не C ++ 11). Це додатковий шар абстракції (і непотрібний), який роздуває інтерфейс, що не простіше. І передбачити Qt не так просто, як BOOST_FOREACH, оскільки він, зокрема, не такий безпечний і не має однакової широти підтримки (BOOST_FOREACH може застосовуватися до будь-якого діапазону, для будь-якої версії C ++, де, як вимагає Qach в QT, C + +03 відповідність). Прогнози QT слід уникати будь-якою ціною.
Аліса,

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 ++ 11 та BOOST версії foreach, завдяки чому звучить так, що версія Qt побудована з однієї з цих двох, що не є AFAICT. Я впевнений, що це не те, що ви мали на увазі, але саме так воно виходить. Звідси "оманлива інформація".
weberc2

It's an additional layer of abstraction (and an unnecessary one) that bloats the interface, which is not easier.Досі незрозуміло, з чим ви порівнюєте. C ++ 03 ітераторів? C ++ 11 ітераторів? BOOST_FOREACH? Все вищеперераховане?
weberc2

1
Я просто кажу, що ви часто дуже неоднозначні щодо того, до якого методу ітерації ви звертаєтесь. Я вважаю, що ви думаєте, що ви зрозуміли і ваша мова є розумною, але здається дивним відмовитись від уточнення. Я погоджуюсь не погоджуватися, я думаю.
weberc2

23

Контейнери STL:

  • Мати гарантії виконання
  • Може використовуватися в алгоритмах STL, які також мають гарантії продуктивності
  • Може використовуватись сторонніми бібліотеками C ++, як-от Boost
  • Є стандартними та, ймовірно, переживають власні рішення
  • Заохочуйте загальне програмування алгоритмів та структур даних. Якщо ви пишете нові алгоритми та структури даних, які відповідають STL, ви можете використовувати те, що STL вже надається безкоштовно.

5
Все вищезазначене, окрім того, що є стандартним, стосується і QTL, за умови, що ви компілюєте Qt із підтримкою STL (за замовчуванням). Підтримка STL включає в себе функції ітератора, контейнери typedefs (const_iterator тощо), функції перетворення (в / з STL).
rpg

2
Qt не є власником
txwikinger

3
@rpg Майже всі вони не відповідають дійсності QTL; QTL не має чітких гарантій продуктивності (оскільки вони легко порушували їх у минулому), не відповідають стандартам STL (немає зворотнього зв'язку, і тому їх не можна використовувати при сильному прискоренні), не є стандартними (вони постійно змінюються між версіями) і не заохочувати загальне програмування (наприклад, вони не мають аргументів шаблону для алокаторів).
Аліса

15

Контейнери Qt використовують ідіому копіювання під час запису.


2
+1, може бути суттєвою перевагою у продуктивності та ресурсі
RedGlyph

32
Або може бути суттєвим недоліком. Дивіться gotw.ca/publications/optimizations.htm
Kaz Dragon

3
Здається, атомний запас виглядає досить добре: labs.trolltech.com/blogs/2006/10/16/…
rpg

Контейнери STL можуть безкоштовно використовувати будь-які ідіоми, якщо вони відповідають гарантіям продуктивності та специфікації. COW діє навіть за C ++ 11 / C ++ 14 STL.
Аліса

1
@Alice COW не є дійсною реалізацією протягом більшої частини часу, оскільки вона порушує складність стандарту і гарантує чинність ітератора майже в будь-якому випадку. Одним з небагатьох класів, який можна було б реалізувати за допомогою COW, був, std::basic_stringі стандарт вживав заходів з C ++ 11, щоб зробити це невідповідним.
Тіаго Гомес

9

Однією з головних проблем є те, що API Qt очікує, що ви надасте дані в контейнерах Qt, тому ви можете просто використовувати контейнери Qt, а не перетворюватись між ними вперед і назад.

Крім того, якщо ви вже використовуєте контейнери Qt, можливо, буде більш оптимально використовувати їх виключно, оскільки вам не доведеться включати файли заголовків STL і потенційно посилатись у бібліотеки STL. Однак, залежно від вашої ланцюжка інструментів, це все одно може статися. Чисто з точки зору дизайну, послідовність, як правило, хороша річ.


1
Швидкість, з якою вам доведеться "перетворювати назад і назад" між контейнерами STL і Qt в реальній програмі, яка використовує STL, за винятком випадків, коли взаємодія з Qt зазвичай сильно завищена. Більшу частину часу ви робите деякий std :: перетворення, що надходить до / із презентаційного шару (для якого використовується Qt), і ви отримуєте контейнерний перемикач безкоштовно. Зацікавлені сторони можуть переглядати проекти.kde.org/ projects/ kde/kdepim/repository/ reitions/…, щоб переконатися в цьому.
Марк Муц - mmutz

8

Якщо дані, з якими ви працюєте, в основному використовуються для керування інтерфейсом на основі Qt, то обов'язково використовуйте контейнери Qt.

Якщо дані здебільшого використовуються внутрішньо в додатку, і ви, ймовірно, ніколи не будете переносити далеко від Qt, тоді забороняючи проблеми з продуктивністю, використовуйте контейнери Qt, оскільки це полегшить обробку бітів даних, що надходять до інтерфейсу користувача.

Якщо дані в основному використовуються спільно з іншими бібліотеками, які знають лише про контейнери STL, тоді використовуйте контейнери STL. Якщо у вас є така ситуація, ви перебуваєте в біді, незважаючи ні на що, тому що ви збираєтеся робити багато переносів назад і назад між типами контейнерів незалежно від того, чим займаєтесь.


7

Крім різниці COW, контейнери STL набагато ширше підтримуються на різних платформах. Qt є достатньо портативним, якщо ви обмежите свою роботу на "мейнстрім" платформах, але STL доступний і на багатьох інших більш незрозумілих платформах (наприклад, DSPs Texas Instruments ').

Оскільки STL є стандартним, а не контрольованим однією корпорацією, в цілому існує більше програмістів, які можуть легко читати, розуміти та змінювати код STL та більше ресурсів (книги, онлайн-форуми, конференції тощо) для їх підтримки. робити це, ніж є для Qt. Це не означає, що слід ухилятися від Qt тільки з цієї причини; тільки в цьому випадку, якщо всі інші рівні рівні, вам слід за замовчуванням застосовувати STL, але, звичайно, всі речі рідко рівні, тому вам доведеться вирішувати у власному контексті, який має найбільш сенс.

Що стосується відповіді AlexKR: продуктивність STL гарантована в межах, але дана реалізація може використовувати деталі, що залежать від платформи, для прискорення їх STL. Тож у цьому сенсі ви можете отримати різні результати на різних платформах, але це ніколи не буде повільніше, ніж явна гарантія (помилки модуля).


9
Що стосується Вашого першого моменту: я припускаю, що ОП стосується проектів, які вже використовують Qt, і тому вони вже обмежені платформами "мейнстрім". Мабуть, мабуть, хтось би зайняв таку важку бібліотеку, як Qt, лише для своїх контейнерних класів.
ThisSuitIsBlackNot

4

Мої п'ять центів: контейнери Qt повинні працювати аналогічно на різних платформах. Хоча контейнери STL залежать від реалізації STL. Можливо, ви отримаєте різні результати ефективності.

EDIT: Я не кажу, що STL "повільніше", але я вказую на ефекти різних деталей реалізації.
Перевірте це , а потім, можливо, і це .
І це не реальна проблема STL. Очевидно, якщо у вас є значна різниця в продуктивності, то в коді є проблема, яка використовує STL.


Контейнери STL всі схожі, незалежно від реалізації. У вас не може бути реалізований вектор, як список поза кадром, оскільки він повинен знаходитися в суміжному блоці пам'яті. STL зазвичай також оптимізований до величезних можливостей на всіх основних платформах.
Yacoby

1
Якщо ви дотримуєтесь того, що обіцяє STL (замість того, щоб припускати, як це реалізовано), у вас ніколи не виникне проблем із переміщенням між платформами зі STL. Те саме з Qt.
Майкл Коне

Це якраз протилежне до істини. Контейнери STL завжди працюють однаково на всіх платформах; якщо їх немає, вони не є STL. QT, однак, різко змінює продуктивність від версії до версії, тому на платформі з QT4.0, а не QT4.8, ви можете отримати серйозні зміни.
Аліса

1
Ви плутаєте два дуже різні типи виконання; алгоритмічна продуктивність та практична обчислювальна продуктивність. Усі реалізації STL гарантують однакову алгоритмічну продуктивність; якщо ваш вектор потребує часу журналу (n) для індексації елемента, це не вектор STL. Ваші посилання вказують на практичну обчислювальну ефективність, що в цьому обговоренні безглуздо; QT змінює свої алгоритми між версіями, і той самий C ++ на різних платформах отримує різну продуктивність. На мій досвід, це набагато більш податливі, ніж відмінності в продуктивності STL.
Аліса

3

Я думаю, це залежить від способу використання Qt. Якщо ви використовуєте його в усьому продукті, ніж це, мабуть, має сенс використовувати контейнери Qt. Якщо ви вмістите його лише до (наприклад) частини інтерфейсу, можливо, краще використовувати стандартні контейнери C ++.


3

Я вважаю, що STL - це чудовий фрагмент програмного забезпечення, однак, якщо я хочу зробити якесь програмування KDE або Qt, то Qt - це шлях. Крім того, це залежить від компілятора, який ви використовуєте, GCC STL працює досить добре, але якщо вам доведеться використовувати скажімо SUN Studio CC, то STL, швидше за все, доставить вам головні болі через те, що компілятор не є STL як такий. У такому випадку, оскільки компілятор зашкодить вам голову, просто використовуйте Qt, щоб врятувати вам неприємності. Тільки мої 2 копійки ...


3

У QVector є (іноді) велике обмеження. Він може виділяти лише цілі байти пам'яті (зауважте, що межа є в байтах, а не в кількості елементів). Це означає, що спроба виділити суміжні блоки пам'яті більше ~ 2 Гб за допомогою QVector призведе до збою. Це відбувається з Qt 4 та 5. std :: вектор не має такого обмеження.


0

Основна причина для роботи з контейнерами STL - це якщо вам потрібен спеціальний розподільник, щоб повторно використовувати пам'ять у дуже великих контейнерах. Припустимо, наприклад, що у вас є QMap, який зберігає 1000000 записів (пари ключів / значень). У Qt це означає рівно 1000000000 асигнувань (new дзвінків), незалежно від того. У STL ви завжди можете створити спеціальний розподільник, який внутрішньо розподіляє всю цю пам'ять одразу та призначає її кожному запису, коли карта заповнюється.

Моя порада - використовувати контейнери STL при написанні критичних алгоритмів ефективності в бізнес-логіці, а потім перетворити їх назад в контейнери Qt, коли результати будуть готові, відображаючись вашими елементами управління та формами користувальницького інтерфейсу, якщо це необхідно.


Тут не намагаються захищати QTL, але ви можете спеціалізуватися QMapNode<K,V>на своєму K, Vщоб забезпечити своє operator new.
Марк Муц - mmutz
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.