Работали ли вы с коллекциями Qt?

«Работали ли вы с коллекциями Qt?» — вопрос из категории Qt, который задают на 25% собеседований C/C++ Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Да, активно использовал Qt-контейнеры в разработке GUI-приложений. Они интегрированы с экосистемой Qt и имеют особенности по сравнению со STL.

Ключевые отличия Qt-контейнеров от STL:

  1. Copy-on-write (неявное разделение данных):

    QList<QString> list1 = {"A", "B", "C"};
    QList<QString> list2 = list1; // Нет копирования данных, только ссылка
    list2.append("D"); // Только теперь происходит реальное копирование
    // list1 остаётся ["A", "B", "C"]
    // list2 становится ["A", "B", "C", "D"]
  2. Интеграция с сигналами/слотами и QVariant:

    
    // QList<QVariant> для передачи разнотипных данных
    QList<QVariant> rowData;
    rowData << QVariant("John Doe") << QVariant(30) << QVariant(QDate::currentDate());

// Использование в QAbstractItemModel QVariant MyModel::data(const QModelIndex& index, int role) const { if (role == Qt::DisplayRole) { return m_data[index.row()][index.column()]; // QList<QList> } return QVariant(); }


3. **Потокобезопасные итераторы (Java-style и STL-style):**
```cpp
// Java-style (удобно, но менее эффективно)
QList<int> numbers = {1, 2, 3, 4, 5};
QListIterator<int> it(numbers);
while (it.hasNext()) {
    qDebug() << it.next();
}

// STL-style (более эффективно)
for (auto it = numbers.begin(); it != numbers.end(); ++it) {
    *it *= 2; // Можно модифицировать
}

// Range-based for (C++11)
for (int& num : numbers) {
    num += 10;
}
  1. Специализированные контейнеры для GUI:
    
    // QMap для хранения настроек с человеко-читаемыми ключами
    QMap<QString, QVariant> settings;
    settings["window/title"] = "My App";
    settings["window/size"] = QSize(800, 600);
    settings["recent/files"] = QStringList{"file1.txt", "file2.txt"};

// QHash для быстрого поиска виджетов по ID QHash<WidgetId, QWidget*> widgetRegistry; widgetRegistry[WidgetId::MainWindow] = mainWindow; widgetRegistry[WidgetId::Toolbar] = toolbar;

// Поиск: O(1) в среднем случае if (auto widget = widgetRegistry.value(WidgetId::Toolbar)) { widget->setVisible(false); }


5. **Алгоритмы QtAlgorithms (устарели в пользу std):**
```cpp
QList<int> values = {5, 2, 8, 1, 9};
// Qt-way (устаревший, но встречается в legacy коде)
qSort(values.begin(), values.end());

// Современный подход - используем std
std::sort(values.begin(), values.end());

// Qt-специфичные алгоритмы
QStringList names = {"John", "Jane", "Bob"};
if (names.contains("Jane", Qt::CaseInsensitive)) {
    // ...
}

Рекомендации по использованию:

  • Используйте QVectorQList для большинства случаев (в Qt 6 они унифицированы)
  • QHash вместо QMap, если не нужна сортировка по ключу
  • Для интерфейсов библиотек используйте STL-контейнеры для совместимости
  • Помните о неявном разделении при многопоточном доступе