Содержание цикла обзора выступлений CppCon 2017:



Обзор выступления Ларса Кнолла (Lars Knoll), являющегося техническим директором Qt Company. Не ждите от этого выступления слишком многого. В квадратных скобках курсивом мои примечания.



Спасибо за возможность немного рассказать о Qt. Это C++ фреймворк. Его принципы и философия немного отличаются от тех, которые вам знакомы по стандартной библиотеке. [Вопрос к залу] Просто для информации, многие ли из вас знают Qt и использовали его раньше? Вау! Спасибо, здорово! Это фантастика! Тогда я буду рассказывать о вещах, которые вы вероятно уже знаете.


Что такое Qt?


Возможно, это самый всеобъемлющий C++ фреймворк. Но это не только фреймворк, это также разнообразные инструменты, которые помогают разрабатывать embedded-устройства, UI-технология Qt Quick, не относящаяся к C++, но интегрируемая с ним.


Две лицензии: коммерческая и LGPLv3/GPLv3. Это открытый проект.


Два продукта:


  • Qt for Application Development (Desktop & Mobile Platforms: Android, Linux, Windows, Mac, iOS)
  • Qt for Device Creation (Embedded platforms: Android, Linux, Windows,QNX, VxWorks, Green Hills Software (IOT, интернет вещей))

Qt for Application Development


Qt модули


В основе находятся неотъемлемые библиотеки. Самая главная — Core, содержащая основные классы, I/O, работу с файлами и т.д. Библиотека GUI — основа графического интерфейса. И много других.


Qt for Device Creation


Qt embedded


Qt Creator


Кроссплатформенная среда разработки для настольных, мобильных и встраиваемых систем. Многие используют ее для программирования на чистом C++, без Qt. Поддерживает интеграцию различных инструментов (профилировщики, отладчики...), автокомплит, VCS...


Qt Creator
Раннее обнаружение ошибок с помощью Qt Creator и CLang static analyzer


История


Перенесемся на 26 лет назад. Студенты Haarvard Nord и Eirik Chambe-Eng задумались над новым проектом. В то время они занимались разработкой GUI для системы, которая работала на Unix, Macintosh и Windows. Это было трудно. Летом 1990 они решили, что им нужна объектно-ориентированная система отображения.


В 1993 было разработано первое графическое ядро


early Qt


Эта версия называлась Quasar. Тогда не существовало пространств имен. Motif (библиотека элементов интерфейса и набор спецификаций для разработки графических интерфейсов под X Window System) имела свой префикс. Поэтому был добавлен префикс "Q", который исполнял роль пространства имен. Сейчас от той версии сохранилось многое. Остался QObject — центральная часть, реализующая механизм сигналов/слотов. А также QEvent, QFont, QPainter, QColor.


В 1994 они убедили своих жен поддержать их финансово пару лет, и основали компанию Trolltech.


Trolltech Site
Ранняя версия сайта Trolltech


Проект был еще довольно сырой. К тому же продажи ПО через интернет в те времена не пользовались популярностью, предпочитали физические носители. Соответственно денег было мало.


1996: Qt 1.0


Работал полностью без шаблонов. Поэтому было несколько специализированных списков для указателей, целых чисел и пр. Поддерживались Windows 95/NT и UNIX/X11. Версия для UNIX была с открытым кодом, так как маленькой компании нужно было как-то распространить свой продукт.


New Project: Kool Desktop Environment (KDE)


В 1997 Маттиас Эттрих (известный за свой вклад в проект KDE) решил использовать Qt для создания KDE. Вероятно это и стало причиной по которой Qt "взлетел".


first_kde


1999: Qt 2.0


Был выпущен под лицензией GPL. Появилась поддержка юникода. Проекту был предоставлен венчурный капитал. Количество сотрудников за год увеличилась с 5 до 50.


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


qt_designer
первая версия


В это время я перешел на работу в Trolltech [И поэтому автор стал далее использовать местоимение "мы"]


2001: Qt 3


Мы заменили explicit sharing на implicit sharing для строк. У людей появилась куча проблем со строками. Тогда мы решили оставить implicit sharing, но создавать новый внутренний экземпляр, когда строка меняется (copy-on-write) [далее чуть подробнее].


Стали использовать больше шаблонов, C++98. Появился qobject_cast<> (аналог dynamic_cast для QObject, но не использующий RTTI). Открыты исходники для Mac.


2005: Qt 4


Тщательно пересмотрели шаблонные и вспомогательные классы. Перешли от хранения указателей на значения в контейнерах к хранению самих значений. Implicit sharing контейнеры стали использовать атомарный подсчет ссылок. Открыты исходники для Windows. Для Windows это было сделано в последнюю очередь, потому что нам был нужен доход и покупатели чтобы выжить.


Nokia приобретает Trolltech


Nokia была заинтересована в общем API для их платформ (S40, Symbian & Maemo/MeeGo). Были получены огромные инвестиции в Qt. Мы долгое время хотели разработать кроссплатформенное IDE, но не было средств. Руководство предлагало Eclipse, но она не очень хороша для C++. C Nokia наше желание стало возможным и был создан Qt Creator. А также Qt Quick. Еще мы стали работать над интеграцией движка WebKit. Nokia сменила лицензию с GPL на LGPL, что сделало фреймворк еще более свободным.


В 2012 мы разошлись с Nokia.


2011/2012 Qt 5


Digia приобрела Qt.


Портировать на новые платформы было трудно, поэтому добавили слой абстракции. Хорошо поработали над графическим интерфейсом, он перестал быть статичным. Например, это видно по окошку Dock Widget во время перемещения.


2016: Qt Company отделилась от Digia


Qt Company сегодня


250 сотрудников, годовой доход 32 миллиона евро. Около миллиона активных пользователей.


Qt сейчас


Наши цели:


  • Поддержка старого кода
  • Интуитивность
  • Самодокументированность
  • API, простое для изучения и использования
  • Производительность

Сохранение простоты


C++ имеет очень крутую кривую обучения, из-за чего новичкам бывает тяжело. Вся эта сложность требуется в редких случаях. А Qt пользуются не только гуру C++. Вы редко увидите разработчика приложений возящегося с шаблонным метапрограммированием.


Реализация


[Поверхностно рассказывается про основы QObject, Сигналы/Слоты, moc, про которые написано в любом руководстве, пропустил]


Implicitly shared


Подробнее: Implicitly shared


Многие классы реализованы примерно так:


class QFont
{
    void setPointerSize(int pt)
    {
        if (d->refCount != 1)
            detach();
        d->pointSize = pt;
    }
private:
    detach();
    QFontPrivate *d;
};

class QFontPrivate
{
    QBasicAtomicInt refCount;
    int pointSize = -1;
    int weight = QFont::Normal;
};

Это позволило нам быть более свободными при добавлении и удалении членов класса. При изменении объекта создается копия внутренних данных. Достоинства такого подхода:


  • Объекты ведут себя почти как примитивные типы
  • Простое и быстрое копирование объекта
  • Объект может быть передан по значению
  • Потокобезопасно

Недостатки:


  • Небольшое ухудшение производительности из-за атомарного счетчика
  • Небольшое изменение семантики итерирования
  • У Range-for циклов могут быть проблемы:

for(auto c : qvector) //Отделяется (detached) если вектор не константный
for(auto c : qAsConst(qvector)) //Решение

[В первой строке detach действительно вызывается, но создание внутренней копии произойдет только если счетчик будет больше единицы, например:]


QVector<int> v1 = { 1, 2, 3 };
QVector<int> v2 = v1; //Копирования внутренних данных не произойдет, просто v1 и v2 будут ссылаться на одну и ту же копию
for (auto c : v1) //А вот здесь произойдет, при вызове v1.begin()

Заполнение недостающего в стандартной библиотеке:


  • QString с поддержкой юникода, который C++ нормально не поддерживает.
  • QLocale
  • QDate/QTime/QDateTime/QTimeZone
  • QAtomic и потоки. Реализованы до C++11
  • Работа с файловой системой, I/O, сетью
  • Графика

Qt Quick


[Самые-самые основы QML, ничего нового. Пропустил]


Будущие релизы


  • Qt 5.9 — текущий релиз (long term supported — 3 года)
  • Qt 5.9.2 — скоро
  • Qt 5.10 — скоро бета, релиз в ноябре
  • Qt 5.11 — май 2018
  • Qt 5.12 — ноябрь 2018 (возможный кандидат следующего long term supported)

Графика


Включение различных графических API в Qt Scene (OpenGL, Vulkan, Metal, Direct3D, Software Rasterization)


Плановая работа


  • Улучшение производительности
  • Распознавание речи (цифровой помощник?)
  • AR/VR
  • Инструменты IDE (рефакторинг, workflow)

C++14 & 17


Мы используем C++11 в той мере, в которой позволяет VS2013. Мы бы хотели использовать:


  • if constexpr
  • Initializers в if/switch
  • Structured bindings
  • Overaligned data

Уже используем __has_include, [[deprecated]], [[fallthrough]], [[nodiscard]]. Добавили QStringView.


C++20


Мог бы стать очень интересным для Qt: концепты, модули, рефлексия (может быть даже удалось бы избавиться от moc когда-нибудь в будущем).


Вопросы и ответы


Что вы скажете о безопасности Qt?

Конечно мы работаем над этим, тратим много времени, выпускаем патчи, апдейты. Наш security mailing list достаточно небольшой.


Как произносится: "кьютИ" или "кьЮт" [очень мягкая "т" в обоих случаях]?

Хороший вопрос! В нашей компании и в тех которые работают с нами используется "кьЮт", хотя в США преимущественно "кьютИ". [А как у вас? Добавил голосовалку]


Программирование на Qt отличается от программирования на C++. Что вы думаете о дублировании функционала — например QVector и многого другого? Планируете объединить или что?

В идеале да, но есть проблемы. Во-первых, из-за поддержки старого кода. Во-вторых, некоторые Qt классы лучше, например QString (интерфейсные методы типа преобразования регистра, юникод). Задают много вопросов про схожие контейнеры. Я советую выбирать наиболее подходящие.


Сейчас в Qt используются сырые владеющие указатели (raw owning pointers). Не пора ли их заменить на умные? Сейчас объект с умным указателем нельзя передать в Qt, потому что у него появится родитель.

Это очень сложно. И сломается весь старый код.


Если вашкод опенсорсный, то откуда доход?

От продаж коммерческой версии.


Почему бы к QObject и производным классам не добавить конструктор перемещения? С конструктором копирования это понятно [почему нет конструктора копирования].

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


Вы проводили оценку быстродействия модели copy-on-write для строк по сравнению с простым копированием?

Для коротких строк копирование быстрее. Скоро выйдет обновление, в котором будет реализован подобный механизм для коротких строк.


Как насчет поддержки других графических API?

Если мы говорим о 3D API, типа Apple Metal, Vulkan, Direct 3D 12, то это сложно.

Комментарии (25)


  1. karter
    02.10.2017 21:58
    +11

    Прочиталось очень быстро, и история показалась какой-то коротко.
    А читаю «кутЭ.»


    1. Fil Автор
      02.10.2017 22:19
      +1

      Я сильно урезал только части, в которых рассказывалось об основах (QObject, сигналы/слоты, QML), потому что это известно всем, кто хотя бы немного программировал с Qt. Это просто конспект, а выступление было скучноватым. Немного подробнее об истории было на Хабре.


      1. karter
        02.10.2017 22:20

        О, спасибо за ссылку.


  1. QtRoS
    02.10.2017 23:34
    +2

    Программирование на Qt отличается от программирования на C++. Что вы думаете о дублировании функционала — например QVector и многого другого? Планируете объединить или что?
    Да, отличается, в лучшую сторону. Вот яркий пример: string replace. Хочется писать код не теряя мысль, а не офигевать от того, как сложно приходится делать простые вещи. ИМХО, но именно этим современный C++ (а если быть точным, то его стандартная библиотека) и не впечатляет. Qt на порядок удобнее.


    1. Falstaff
      03.10.2017 00:51

      Могли бы реализовать не функциями-членами, а внешними алгоритмами — как в бусте. Вроде бы это C++ way — делать алгоритмы обобщёнными (boost string algorithms вроде работает и не только с std::basic_string). Тогда не был бы нужен QString, дублирующий стандартную строку. Это я к тому, что всё относительно. Вопрос вкуса и философии языка в какой-то мере.


      1. QtRoS
        03.10.2017 09:04
        +4

        QString это не только алгоритмы над строками (append, prepend, replace, trimmed, split, etc), а встроенная поддержка форматирования (arg) и преобразования из/во что угодно (числа, латиница, string, wstring, nsstring, массивы, etc). Все это сделано методами, не нужно включать отдельные заголовочные или использовать итераторацию по строке для преобразования, однострочный код остается однострочным. Да он безусловно медленней — в Qt почти все классы построены по принципу паттерна мост (bridge, pimple, d-pointer), то есть любое использование подразумевает обращение по указателю, что не есть хорошо с т.з. локальности данных (data locality). Но удобство сопоставимо с C#, Java, Python и т.д., для разработки приложений это перевешивает.
        C++ из-за своей ниши не может позволить себе из коробки никаких явных расходов, это понятно, но в том же Go такая же идеология (неявно, за кулисами ничего не происходит), и стандартная библиотека поудобнее будет, хоть она и в процедурном стиле. Поэтому по моему мнению не стоит распространять приемы чистого C++ на кроссплатформенный швейцарский (норвежский?) нож.


        1. RPG18
          03.10.2017 11:32

          то есть любое использование подразумевает обращение по указателю, что не есть хорошо с т.з. локальности данных (data locality).

          Но с другой стороны имеем implicit sharing.


        1. monah_tuk
          05.10.2017 03:12

          QString это не только алгоритмы над строками (append, prepend, replace, trimmed, split, etc), а встроенная поддержка форматирования (arg) и преобразования из/во что угодно (числа, латиница, string, wstring, nsstring, массивы, etc).

          Я бы отдельно и особо выделил: Unicode.


    1. nolane
      03.10.2017 01:22

      Хочется верить, что эта функция отсутствует не просто так, а для того что бы предостеречь программистов от неэффективного кода и направить в сторону эффективного.
      Если как в том примере нужно форматированое генерирование строк, то stringstream вам в руки.


      1. oYASo
        03.10.2017 14:19
        +2

        Ну то есть ужасно медленный stringstream мы оставляем для форматирования, а эффективную и типичную функцию replace не делаем. Типичный комитет по стандартизации.


        1. nolane
          03.10.2017 15:50

          эффективную функцию replace

          По вашему replace быстрее <<?


          1. oYASo
            03.10.2017 20:27
            +1

            С точки зрения С++ — и replace, и << — функции. Предполагаю, что их эффективность определяется их реализации. Угловые скобки не работаю быстрее только потому, что это не буквы.

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


            1. Falstaff
              03.10.2017 22:13

              Я боюсь, что replace() сложнее реализовать более эффективно чем можно выжать из stringstream. Если stringstream со своей строкой и reserve() перед вызовом — то должна быть одна аллокация в куче и дальше только копирование выводимых фрагментов (заметьте, что в вашем же примере strinstream without construction в целом не сильно отстаёт от lexical_cast, а где-то и опережает). В случае же с replace() у вас в любом случае две аллокации в куче и вся стока копируется во время замены. Поэтому "типичная" replace() — возможно, а "эффективная" — сложно сказать.


            1. nolane
              04.10.2017 00:39

              Я предполагаю, что << должно работать быстрее, потому что это добавление в конец, а не удаление + вставка, в каком то месте в середине строки, которое ещё нужно найти.


    1. yarric
      03.10.2017 08:47
      -3

      Программирование на Qt отличается от программирования на C++

      Qt — это не язык вообще, а библиотека к языку. Странное утверждение.


      1. Fil Автор
        03.10.2017 08:57
        +3

        Да, конечно. Имелось в виду то, что концепции, заложенные в Qt, принципы использования Qt, отличаются от тех, которые нам знакомы по std, по рекомендациям программирования на чистом C++, по Core Guidelines.


      1. QtRoS
        03.10.2017 09:18
        +8

        Дополню Fil — Qt это фреймворк в самом каноническом значении этого слова, то есть не только набор функций и классов, а еще и преопределенных приемов по разработке. В русском переводе книги GoF про паттерны употребляется слово «каркас», и оно уместно для Qt, ибо это некоторый каркас (основной цикл обработки событий и инфрраструктурная система классов), который обвешивается функционалом.
        Если еще немного филосовски поразмышлять, то можно обратить внимание на тот факт, что в любом Qt-приложении есть QApplication (QCoreApplication если быть точным). Это серьезная заявка на выход из статуса библиотеки в сторону фреймворка.
        P.S. И если быть совсем точным, то Qt приносит некоторые новшества в сам язык, хоть и завуалированно. Поэтому утверждение не абсурдное.


  1. UA3MQJ
    03.10.2017 01:47
    -1

    Я произношу КОТЭ )


  1. geher
    03.10.2017 07:58

    Кютэ (наверное, изучение немецкого в школе сказывается).
    Все жду от них готовой 64 бит сборки на mingw.


    1. Goodkat
      03.10.2017 22:08

      В немецком ку-те.


      1. geher
        03.10.2017 22:26

        Это да.
        Но когда на остаточное влияние немецкого слегонца накладывается английский, который изучался позже, то как раз и получается "ни туда, ни сюда". Еще не "кью", но уже и не "ку". Короче говоря, "Кин-дза-дза" какая-то получается.


      1. monah_tuk
        05.10.2017 03:15

        Немецкий не учил, но произношу именно так :)


  1. Idot
    03.10.2017 08:07

    Qt звучит как cutie (читается "кьютИ" /?kju?ti/), так называют симпатичную милую девушку :)


  1. vitanje
    03.10.2017 17:04

    Любая инфа по любимому Qt всегда полезна.) респекты и благодарности)


  1. monah_tuk
    05.10.2017 03:18

    Многие используют ее для программирования на чистом C++, без Qt.

    Не только на C++, но и на Plain C. А я ещё и для Baremetal разработки, тыц.