Контейнеры 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_stringUnicode. Он также предлагает эффективную реализацию 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-битной архитектуре для использования памяти, чтобы убедиться в этом.
Марк Мутц - Мамц

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»), поэтому я немного отредактировал его. Спасибо
Julien-L

Абсолютно хорошо сказано. Если вы делаете QT, используйте QT! Представьте себе момент «WTF» для сопровождающего, когда он открывает приложение QT и видит, что QT и STL используются взаимозаменяемо. Это может оказаться (ненужным) кошмаром.
Пит

5
@ It'sPete STL является частью стандарта; QT нет. Любой код, использующий стандарт, никогда не должен запускать момент «WTF».
Алиса

6
Римляне поместили своих пленников в Колизей, а затем выследили их со львами. Если вы знаете лучше, не следуйте местным привычкам. В Qt это так же верно, как и для современного человека в Римской империи ...
Марк Муц - Мамц

1
@mmutz вы говорите , что , как это плохо, я хотел бы поставить код , который я нашел в том , что Колизей и смотреть шоу
SLF

65

Контейнеры Qt более ограничены, чем контейнеры STL. Несколько примеров того, где STL лучше (все, что я использовал в прошлом):

  • STL стандартизирован, не меняется с каждой версией Qt (Qt 2 имел QList(на основе указателя) и QValueList(на основе значения); Qt 3 имел QPtrListи QValueList;; Qt 4 теперь имеет QList, и это совсем не похоже на QPtrList или QValueList ).
    (Т. Е Даже если вы в конечном итоге с помощью контейнеров Qt, используйте STL-совместимый API подмножество push_back(), не append(), front()не first()...) , чтобы избежать портирование еще раз прийти Qt 5. В обоих Qt2-> 3 и Qt3-> 4 переходы, изменения в контейнерах Qt были среди тех, которые требуют наибольшего оттока кода.
  • Все двунаправленные контейнеры STL имеют rbegin()/ rend(), делая обратную итерацию симметричной для прямой итерации. Не все контейнеры Qt имеют их (ассоциативные не имеют), поэтому обратная итерация излишне сложна.
  • Контейнеры STL имеют диапазон insert()от разных, но совместимых типов итераторов, что делает их std::copy()гораздо реже необходимыми.
  • Контейнеры STL имеют Allocatorаргумент шаблона, что делает пользовательское управление памятью тривиальным (требуется typedef) по сравнению с Qt (fork of QLineEditrequired for s/QString/secqstring/). РЕДАКТИРОВАТЬ 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, похоже, в данный момент испытывает недостаток в развитии.

РЕДАКТИРОВАТЬ 20150106 : Потратив некоторое время, пытаясь обеспечить поддержку C ++ 11 для контейнерных классов Qt 5, я решил, что это не стоит этой работы. Если вы посмотрите на работу, которая вкладывается в реализацию стандартных библиотек C ++, совершенно ясно, что классы Qt никогда не догонят. Мы выпустили Qt 5.4 сейчас иQVector до сих пор не перемещаем элементы в перераспределениях, не имеемemplace_back()или rvalue-push_back()... Мы также недавно отклонилиQOptionalшаблон класса, ожидаяstd::optionalвместо этого. Аналогично дляstd::unique_ptr. Я надеюсь, что эта тенденция продолжается.


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

QVectorимеет crbeginи друзей с Qt 5.6
Барт Louwers

@Alex: правильно, я добавил простые, но не у всех контейнеров Qt они есть (пока вы не используете std::reverse_iteratorчерез сломанные QHash/ QMapитераторы, которые при разыменовании возвращают mapped_typeвместо value_type). Ничего, что не может быть исправлено, но см. Мой РЕДАКТИРОВАТЬ с 2015 года.
Марк Мутц - mmutz

@ MarcMutz-mmutz Спасибо за разъяснения.
Барт Louwers

Возможно, стоит добавить в список тот факт, что, например, QVectorиспользует в intкачестве индекса, ограничивая таким образом 31-битные размеры (даже в 64-битных системах). Более того, он даже не может хранить INT_MAXэлементы размером более 1 байта. Например, наибольшее значение, которое .size()я мог иметь в QVector<float>x86_64 для Linux, составляло 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 стиль foreach

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

И это настолько просто, что нет никакой причины использовать что-либо еще (если только вы не поддерживаете C ++ 11).

Мой любимый, однако, это:

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

Итак, как мы видим, этот интерфейс не дает нам ничего, кроме дополнительного интерфейса, поверх уже гладкого, обтекаемого и современного интерфейса. Добавление ненужного уровня абстракции поверх уже стабильного и удобного интерфейса? Не моя идея "проще".

Кроме того, интерфейсы Qt foreach и java добавляют накладные расходы; они копируют структуру и обеспечивают ненужный уровень косвенности. Это может показаться не таким уж большим, но зачем добавлять уровень накладных расходов, чтобы обеспечить не намного более простой интерфейс? У Java есть этот интерфейс, потому что у java нет перегрузки операторов; С ++ делает.

безопаснее

Обоснованием, которое дает 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 действительно может сделать что-то легче, как и Intrusive Containers, такие как поддерживаемые 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".итераторы Qt в стиле Java не были добавлены в C ++ 11; они предшествуют этому. В любом случае, Qt foreach(QString elem, list)так же прост, как foreach в C ++ 11 или BOOST_FOREACH, и работает с компиляторами, совместимыми с pre-C ++ 11.
weberc2

@ weberc2 Вы в замешательстве; Итераторы в стиле Java Qt добавляются поверх итераторов C ++ (не C ++ 11). Это дополнительный уровень абстракции (и ненужный), который раздувает интерфейс, что не проще. И foreach для Qt не так прост, как BOOST_FOREACH, так как он не столь безопасен и не имеет такой же широты поддержки (BOOST_FOREACH может применяться к любому диапазону, для любой версии C ++, где для foreach в QT требуется C +). +03 соответствия). Следует избегать foreach 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".(выделение мое) Вы сказали это сразу после того, как показали нам версии foreach для C ++ 11 и BOOST, и это звучит так, будто версия 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 включает функции итератора, определения типа контейнера (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
Считается, что атомный рефконт довольно неплох
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 :: transform, приходящее на / из уровня представления (который использует Qt), и вы получаете переключатель контейнера бесплатно. Заинтересованные стороны могут перейти к projects.kde.org/projects/kde/kdepim/repository/revisions/… чтобы убедиться в этом.
Марк Мутц - ммвц

8

Если данные, с которыми вы работаете, в основном используются для управления пользовательским интерфейсом на основе Qt, то обязательно используйте контейнеры Qt.

Если данные в основном используются внутри приложения, и вы вряд ли сможете портировать их с Qt, то, исключая проблемы с производительностью, используйте контейнеры Qt, поскольку это облегчит работу с битами данных, поступающими в пользовательский интерфейс.

Если данные в основном используются вместе с другими библиотеками, которые знают только о контейнерах STL, используйте контейнеры STL. Если у вас возникла такая ситуация, то вы попали в беду, несмотря ни на что, потому что вы собираетесь много портировать туда и обратно между типами контейнеров, независимо от того, что вы делаете.


7

Помимо разницы в COW, контейнеры STL гораздо шире поддерживаются на различных платформах. Qt достаточно портативен, если вы ограничиваете свою работу «основными» платформами, но STL доступен и на многих других более неясных платформах (например, DSP от Texas Instruments).

Поскольку STL является стандартным, а не управляемым одной корпорацией, то, как правило, есть больше программистов, которые могут легко читать, понимать и изменять код STL, и больше ресурсов (книг, онлайн-форумов, конференций и т. Д.) Для их поддержки в делать это, чем есть для Qt. Это не значит, что нужно уклоняться от Qt только по этой причине; просто при прочих равных условиях вы должны использовать STL по умолчанию, но, конечно, все редко бывают равными, поэтому вам придется выбирать в своем собственном контексте, который имеет больше смысла.

Что касается ответа AlexKR: производительность STL гарантируется в определенных пределах, но в данной реализации могут использоваться детали, зависящие от платформы, для ускорения их STL. Таким образом, в этом смысле вы можете получить разные результаты на разных платформах, но это никогда не будет медленнее, чем явная гарантия (по модулю ошибок).


9
Относительно вашего первого замечания: я предполагаю, что OP имеет в виду проекты, которые уже используют Qt, и поэтому уже ограничены "основными" платформами. Кажется маловероятным, что кто-то использует такую ​​тяжеловесную библиотеку, как Qt, только для своих контейнерных классов.
ThisSuitIsBlackNot

4

Мои пять центов: контейнеры Qt должны работать одинаково на разных платформах. В то время как контейнеры STL зависят от реализации STL. Вы можете получить разные результаты производительности.

РЕДАКТИРОВАТЬ: Я не говорю, что STL "медленнее", но я указываю на эффекты различных деталей реализации.
Пожалуйста, проверьте это , а затем, возможно, это .
И это не настоящая проблема STL. Очевидно, что если у вас есть существенная разница в производительности, то есть проблема в коде, который использует STL.


Контейнеры STL все одинаковые, независимо от реализации. Вы не можете иметь вектор, реализованный как список за кулисами, так как он должен быть в непрерывном блоке памяти. STL также обычно оптимизируется до огромных размеров на всех основных платформах.
Якоби

1
Если вы будете придерживаться того, что обещает STL (вместо того, чтобы предполагать, как это реализовано), у вас никогда не возникнет проблем при перемещении между платформами с STL. То же самое с Qt.
Майкл Кохне

Это полная противоположность истине. Контейнеры STL всегда работают одинаково на всех платформах; если они этого не делают, они не STL. QT, однако, резко меняет производительность от версии к версии, поэтому на платформе с QT4.0, а не с QT4.8, вы можете получить некоторые серьезные изменения.
Алиса

1
Вы путаете два совершенно разных типа исполнения; алгоритмическая производительность и практическая вычислительная производительность. Все реализации STL гарантируют одинаковую алгоритмическую производительность; если ваш вектор занимает log (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 есть (иногда) большое ограничение. Он может выделять только int байты памяти (обратите внимание, что ограничение указывается в байтах, а не в количестве элементов). Это означает, что попытка выделить смежные блоки памяти размером более ~ 2 ГБ с помощью QVector приведет к сбою. Это происходит с Qt 4 и 5. std :: vector не имеет такого ограничения.


0

Основная причина, по которой я могу использовать STL-контейнеры, заключается в том, что вам нужен собственный распределитель, чтобы повторно использовать память в очень больших контейнерах. Предположим, например, что у вас есть QMap, в котором хранится 1000000 записей (пары ключ / значение). В Qt это означает ровно 1000000 миллионов выделений (new вызовов), несмотря ни на что. В STL вы всегда можете создать собственный распределитель, который выделяет всю эту память за один раз и назначает ее каждой записи при заполнении карты.

Я советую использовать контейнеры STL при написании критичных для производительности алгоритмов в бизнес-логике, а затем преобразовывать их обратно в контейнеры Qt, когда результаты будут готовы к отображению элементами управления пользовательского интерфейса и формами, если это необходимо.


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