Qt QMapのキーを効率的に反復処理:keyBegin()徹底解説

2025-05-27

QMap は、キーと値のペアを格納するQtのコンテナクラスです。std::map と同様に、キーによって要素がソートされて格納されます。

QMap::keyBegin() 関数は、この QMap に格納されているキーのみを反復処理するためのイテレータを返します。具体的には、QMap の最初のキーを指す QMap::key_iterator 型のイテレータを返します。

主な特徴

  • 使用目的
    QMap に含まれるすべてのキーを順に処理したい場合に便利です。
  • STLスタイル
    key_iterator はStandard Template Library (STL) スタイルのイテレータであり、++ 演算子で次の要素に進んだり、* 演算子で現在の要素(キー)にアクセスしたりできます。
  • const イテレータ
    keyBegin() が返す key_iterator は、const なイテレータであり、QMap の内容を変更することはできません。
  • キーのみのイテレータ
    key_iterator は、QMap 内の要素のキーにのみアクセスできます。値には直接アクセスできません(通常の QMap::iteratorQMap::const_iterator はキーと値の両方にアクセスできます)。

関数のシグネチャ

QMap<Key, T>::key_iterator QMap::keyBegin() const
  • const: この関数が QMap オブジェクトを変更しないことを示します。
  • key_iterator: QMap のキーを指すイテレータの型です。
  • T: QMap の値の型です。
  • Key: QMap のキーの型です。

使用例

QMap に格納されているすべてのキーを順に出力する例を挙げます。

#include <QCoreApplication>
#include <QMap>
#include <QDebug>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QMap<QString, int> ages;
    ages["Alice"] = 30;
    ages["Bob"] = 25;
    ages["Charlie"] = 35;
    ages["David"] = 28;

    qDebug() << "Mapのキー:";
    // keyBegin() と keyEnd() を使ってキーを反復処理
    for (QMap<QString, int>::key_iterator it = ages.keyBegin(); it != ages.keyEnd(); ++it) {
        qDebug() << *it; // イテレータが指すキーの値を取得
    }

    // C++11以降のレンジベースforループを使う場合 (Qt 5.10以降のkeyValueBegin()/keyValueEnd()も似たようなコンセプトですが、keyBegin()はキーのみ)
    // 直接keyBegin()/keyEnd()をレンジベースforループで使うことはできませんが、
    // QMap::keys() を使えばより簡潔に書くことができます。
    qDebug() << "\nQMap::keys() を使ったキーのリスト:";
    for (const QString& key : ages.keys()) {
        qDebug() << key;
    }

    return a.exec();
}

出力例

Mapのキー:
"Alice"
"Bob"
"Charlie"
"David"

QMap::keys() を使ったキーのリスト:
"Alice"
"Bob"
"Charlie"
"David"
  • QMap::keyBegin(): QMap の最初のキーのみを指すイテレータを返します。QMap::key_iterator 型です。*it でキーのみに直接アクセスできます。
  • QMap::begin() / QMap::constBegin(): QMap の最初の要素(キーと値のペア全体)を指すイテレータを返します。QMap::iterator または QMap::const_iterator 型です。*it でキーと値のペアにアクセスし、it.key()it.value() でそれぞれキーと値を取得できます。


QMap::keyBegin() は、QMap のキーをイテレートする際に非常に便利ですが、イテレータの一般的な落とし穴や QMap の特性に起因する特定の問題があります。

一時オブジェクトからのイテレータ

エラーの状況
QMap::keyBegin() を呼び出すオブジェクトが一時オブジェクトである場合、イテレータが無効になる可能性があります。例えば、ある関数が QMap を値で返し、その戻り値に対して直接 keyBegin() を呼び出してループを行うと、一時オブジェクトが破棄されるため、イテレータが「ぶら下がりポインタ」(dangling iterator)となり、未定義の動作やクラッシュを引き起こすことがあります。

// 誤った例: 一時オブジェクトへのイテレータ
QMap<QString, int> createMap() {
    QMap<QString, int> tempMap;
    tempMap["A"] = 1;
    tempMap["B"] = 2;
    return tempMap;
}

void processKeys() {
    // createMap() が返す一時的なQMapに対して直接イテレータを取得
    // この行の終わりにtempMapは破棄され、イテレータは無効になる
    for (QMap<QString, int>::key_iterator it = createMap().keyBegin(); it != createMap().keyEnd(); ++it) {
        // ここで *it にアクセスするとクラッシュする可能性が高い
        qDebug() << *it;
    }
}

トラブルシューティング
QMap オブジェクトを明示的に変数に格納してからイテレータを使用します。

// 正しい例: QMapをローカル変数に格納
void processKeysCorrectly() {
    QMap<QString, int> myMap = createMap(); // QMapをローカル変数にコピー
    for (QMap<QString, int>::key_iterator it = myMap.keyBegin(); it != myMap.keyEnd(); ++it) {
        qDebug() << *it;
    }
}

または、Qt 5.10以降で導入された QMap::keyValueBegin() やC++17の構造化束縛と組み合わせることで、より安全かつ簡潔に書くことも可能です。ただし、keyBegin()はキーのみを扱うため、厳密には別のイテレータです。

イテレーション中に QMap を変更する

エラーの状況
key_iteratorconst イテレータであるため、イテレータ自身を使って QMap の内容を変更することはできません。しかし、QMap の他の非constメソッド(例: insert(), remove(), operator[])をイテレーション中に呼び出すと、イテレータが無効になる可能性があります。特に要素を削除した場合、その要素を指していたイテレータはぶら下がりポインタになります。

// 誤った例: イテレーション中にQMapを変更
QMap<QString, int> myMap;
myMap["A"] = 1;
myMap["B"] = 2;
myMap["C"] = 3;

for (QMap<QString, int>::key_iterator it = myMap.keyBegin(); it != myMap.keyEnd(); ++it) {
    if (*it == "B") {
        myMap.remove(*it); // !危険! イテレータが無効になる可能性がある
    }
    // 次のループで ++it が未定義の動作を引き起こす可能性
}

トラブルシューティング

  • 削除や変更を行う場合
    • QMutableMapIterator を使用するか、通常の QMap::iteratorQMap::erase() の戻り値を利用してループを継続します。ただし、key_iterator はキーの反復に特化しており、削除には適していません。
    • 一般的には、イテレーション中に要素を削除する際は、削除後に新しい有効なイテレータを取得するか、ループの条件を工夫する必要があります。QMap::erase(iterator) は削除後の次の有効なイテレータを返します。
    • キーのみを削除したい場合は、QMap::keys() でキーのリストを生成し、そのリストを反復処理しながら QMap::remove() を呼び出す方法が安全です(ただし、キーリストの作成にオーバーヘッドが生じます)。
// 正しい例: QMapをコピーしてイテレート(変更を伴う場合)
QMap<QString, int> myMap;
myMap["A"] = 1;
myMap["B"] = 2;
myMap["C"] = 3;

// キーのリストを事前に取得し、それをイテレート
QList<QString> keysToProcess = myMap.keys();
for (const QString& key : keysToProcess) {
    if (key == "B") {
        myMap.remove(key); // QMapの変更は可能だが、イテレーション対象はキーリストなので安全
    }
}

// または、値も含む変更であれば QMap::iterator を使う
QMap<QString, int>::iterator it = myMap.begin();
while (it != myMap.end()) {
    if (it.key() == "B") {
        it = myMap.erase(it); // erase() は次の有効なイテレータを返す
    } else {
        ++it;
    }
}

keyBegin() と keyEnd() の型不一致

エラーの状況
keyBegin()keyEnd() が異なる QMap オブジェクトから呼ばれている場合、比較ができずにコンパイルエラーになるか、実行時エラーになります。これは前述の「一時オブジェクト」の問題と関連することが多いです。

// 誤った例: 異なるQMapインスタンスからのイテレータの比較
QMap<QString, int> map1;
map1["A"] = 1;
QMap<QString, int> map2;
map2["B"] = 2;

// 型は同じだが、異なるインスタンスのイテレータを比較しているため未定義の動作
if (map1.keyBegin() == map2.keyBegin()) {
    // これは意味がないし、危険
}

トラブルシューティング
必ず同じ QMap オブジェクトから keyBegin()keyEnd() を取得し、それらを比較してください。

// 正しい例: 同じQMapインスタンスからのイテレータの比較
QMap<QString, int> myMap;
myMap["A"] = 1;

for (QMap<QString, int>::key_iterator it = myMap.keyBegin(); it != myMap.keyEnd(); ++it) {
    qDebug() << *it;
}

空の QMap をイテレートする際の考慮事項

エラーの状況
空の QMap に対して keyBegin() を呼び出すこと自体は問題ありません。keyBegin()keyEnd() と同じイテレータを返します。しかし、イテレータが有効な要素を指していることを確認せずに *it (dereference) を行うと、未定義の動作になります。通常のループ構造 (for (it = begin(); it != end(); ++it)) を守っていれば、この問題は発生しません。

// 誤った例 (滅多に発生しないが、念のため): 空のマップでの無効なデリファレンス
QMap<QString, int> emptyMap;
QMap<QString, int>::key_iterator it = emptyMap.keyBegin();
// if (it == emptyMap.keyEnd()) { // このチェックなしで
//     qDebug() << *it; // !危険! 空のマップのkeyEnd()をデリファレンスしている
// }

トラブルシューティング
ループの条件 (it != map.keyEnd()) を常に適切に設定し、*it はイテレータが有効な要素を指している場合にのみ呼び出すようにします。

// 正しい例: 空のマップでも安全なイテレーション
QMap<QString, int> emptyMap;
for (QMap<QString, int>::key_iterator it = emptyMap.keyBegin(); it != emptyMap.keyEnd(); ++it) {
    // ループは実行されないので安全
    qDebug() << *it;
}

キーの型が operator<() を提供しない場合

エラーの状況
QMap は内部的にキーをソートして格納するため、キーの型 Keyoperator<() が定義されている必要があります。これが定義されていない場合、コンパイルエラーが発生します。

// 誤った例: operator<() が定義されていないカスタム型をキーに使用
class MyCustomKey {
public:
    int id;
    // operator<() が定義されていない
};

// コンパイルエラーになる
// QMap<MyCustomKey, QString> myMap;
// myMap[MyCustomKey{1}] = "Value";

トラブルシューティング
カスタムのキー型を使用する場合は、operator<() を適切にオーバーロードして、全順序関係が定義されるようにします。

// 正しい例: operator<() を定義したカスタム型
class MyCustomKey {
public:
    int id;
    bool operator<(const MyCustomKey& other) const {
        return id < other.id;
    }
};

QMap<MyCustomKey, QString> myMap;
myMap[MyCustomKey{1}] = "Value 1";
myMap[MyCustomKey{2}] = "Value 2";

for (QMap<MyCustomKey, QString>::key_iterator it = myMap.keyBegin(); it != myMap.keyEnd(); ++it) {
    qDebug() << "Key ID:" << it->id;
}

これらの点を意識することで、QMap::keyBegin() を安全かつ効果的に使用することができます。多くの場合、QMap::keys() を使用してキーのリストを直接取得し、それをレンジベースforループで処理する方が、イテレータを直接扱うよりも簡潔で安全な場合があります。

// ほとんどの場合、これが最も簡潔で安全な方法
QMap<QString, int> myMap;
myMap["Alice"] = 30;
myMap["Bob"] = 25;

for (const QString& key : myMap.keys()) {
    qDebug() << key;
}


QMap::keyBegin() は、QMap に格納されているキーのみを反復処理するためのイテレータを提供します。これは、マップ内のキーの順序に基づいて操作を実行したい場合に特に役立ちます。

例 1: マップのすべてのキーを出力する

これは最も基本的な使用例で、QMap に含まれるすべてのキーを辞書順(キーのソート順)に出力します。

#include <QCoreApplication>
#include <QMap>
#include <QDebug> // デバッグ出力用

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    // QMapを作成し、キーと値のペアを挿入
    QMap<QString, int> studentScores;
    studentScores["Alice"] = 95;
    studentScores["Bob"] = 80;
    studentScores["Charlie"] = 70;
    studentScores["David"] = 90;
    studentScores["Eve"] = 85;

    qDebug() << "--- 学生のスコア (キーのみ) ---";

    // QMap::keyBegin() と QMap::keyEnd() を使ってキーを反復処理
    // QMap::key_iterator は const なイテレータなので、マップのキーを変更することはできません。
    for (QMap<QString, int>::key_iterator it = studentScores.keyBegin(); it != studentScores.keyEnd(); ++it) {
        qDebug() << "学生名: " << *it; // イテレータをデリファレンスするとキー(QString)が得られる
    }

    // C++11以降のレンジベースforループ(QMap::keys() を使うのが一般的でより簡潔です)
    // QMap::keyBegin() は直接レンジベースforループでは使えません。
    qDebug() << "\n--- 学生のスコア (キーのみ、QMap::keys() を使用) ---";
    for (const QString& name : studentScores.keys()) {
        qDebug() << "学生名: " << name;
    }

    return a.exec();
}

出力例

--- 学生のスコア (キーのみ) ---
学生名:  "Alice"
学生名:  "Bob"
学生名:  "Charlie"
学生名:  "David"
学生名:  "Eve"

--- 学生のスコア (キーのみ、QMap::keys() を使用) ---
学生名:  "Alice"
学生名:  "Bob"
学生名:  "Charlie"
学生名:  "David"
学生名:  "Eve"

例 2: 特定の条件を満たすキーのカウント (STLアルゴリズムとの連携)

QMap::key_iterator はSTLスタイルのイテレータなので、std::algorithm の関数と組み合わせて使用できます。ここでは、特定の文字で始まるキーの数をカウントします。

#include <QCoreApplication>
#include <QMap>
#include <QDebug>
#include <algorithm> // std::count_if のために必要

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QMap<QString, int> inventory;
    inventory["Apple"] = 10;
    inventory["Banana"] = 5;
    inventory["Apricot"] = 8;
    inventory["Cherry"] = 12;
    inventory["Avocado"] = 3;

    qDebug() << "--- 'A' で始まる果物の数をカウント ---";

    // 'A' で始まるキーを数えるラムダ関数
    auto startsWithA = [](const QString& key) {
        return key.startsWith("A");
    };

    // keyBegin() と keyEnd() を std::count_if に渡す
    int count = std::count_if(inventory.keyBegin(), inventory.keyEnd(), startsWithA);

    qDebug() << " 'A' で始まる果物の数: " << count;

    return a.exec();
}

出力例

--- 'A' で始まる果物の数をカウント ---
 'A' で始まる果物の数:  3

この例では、QMap::keys() を使用して一時的な QList を作成せずに、直接イテレータを std::count_if に渡すことで、メモリ割り当てのオーバーヘッドを避けることができます。

例 3: キーの範囲に基づいて処理を行う

QMap のキーはソートされているため、keyBegin()keyEnd() と共に、lowerBound()upperBound() といった関数を使って、特定のキー範囲のイテレータを取得することもできます。

#include <QCoreApplication>
#include <QMap>
#include <QDebug>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QMap<int, QString> productCatalog;
    productCatalog[101] = "Laptop";
    productCatalog[105] = "Mouse";
    product[110] = "Keyboard";
    productCatalog[115] = "Monitor";
    productCatalog[120] = "Webcam";
    productCatalog[125] = "Headphones";

    qDebug() << "--- 商品ID 110 から 120 (含む) のキーを出力 ---";

    // ID 110 のキーを指すイテレータを取得
    QMap<int, QString>::key_iterator it_start = productCatalog.lowerBound(110);
    // ID 120 の次のキーを指すイテレータを取得 (upperBoundは排他的)
    QMap<int, QString>::key_iterator it_end = productCatalog.upperBound(120);

    for (QMap<int, QString>::key_iterator it = it_start; it != it_end; ++it) {
        qDebug() << "商品ID: " << *it;
    }

    return a.exec();
}
--- 商品ID 110 から 120 (含む) のキーを出力 ---
商品ID:  110
商品ID:  115
商品ID:  120


QMap::keyBegin() の代替方法

QMap::keys() を使用する (最も一般的で推奨される方法)

QMap::keys() は、マップに含まれるすべてのキーを QList<Key> として返します。この方法が最も一般的で、C++11以降のレンジベースforループと非常に相性が良いです。

利点

  • 柔軟性
    返された QList に対して、さらにリスト特有の操作(ソート、フィルタリングなど)を行うことができます。
  • 安全性
    イテレーション中に元の QMap を直接変更しても、取得済みの QList は影響を受けません(ただし、変更後の QMap には反映されません)。
  • 簡潔性
    コードが非常に簡潔で読みやすいです。

欠点

  • 読み取り専用
    返される QList はキーのコピーなので、このリストを変更しても元の QMap のキーには影響しません。
  • メモリオーバーヘッド
    すべてのキーを新しい QList にコピーするため、大きな QMap の場合はメモリとパフォーマンスのオーバーヘッドが発生する可能性があります。しかし、これは多くの場合、許容できる範囲です。

コード例

#include <QCoreApplication>
#include <QMap>
#include <QDebug>
#include <QList> // QList のために必要

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QMap<QString, int> myMap;
    myMap["apple"] = 1;
    myMap["banana"] = 2;
    myMap["cherry"] = 3;

    // QMap::keys() を使用してキーのQListを取得し、レンジベースforループで処理
    qDebug() << "--- QMap::keys() を使ったキーの反復 ---";
    for (const QString& key : myMap.keys()) {
        qDebug() << "Key: " << key;
    }

    // `QList` を明示的に受け取る場合
    QList<QString> allKeys = myMap.keys();
    qDebug() << "\n--- 取得したQListを操作する例 ---";
    for (const QString& key : allKeys) {
        qDebug() << "処理中のキー: " << key << ", 値: " << myMap.value(key); // キーを使って値にアクセス
    }

    return a.exec();
}

STLスタイルイテレータ (QMap::begin() / QMap::constBegin()) を使用する

QMap::begin() (または constBegin() for read-only access) は、マップの最初の要素(キーと値のペア全体)を指すSTLスタイルのイテレータを返します。keyBegin() とは異なり、イテレータをデリファレンスすると、キーと値の両方にアクセスできます。

利点

  • 効率
    QMap::keys() のように一時的なリストを作成しないため、メモリコピーのオーバーヘッドがありません。
  • キーと値の両方にアクセス可能
    it.key()it.value() を使って、キーと値の両方を同時に処理できます。

欠点

  • C++11以前の構文
    C++11のレンジベースforループとは直接的に互換性がありません(ただし、後述の keyValueBegin()/asKeyValueRange() はこの問題を解決します)。
  • 冗長性
    キーだけが必要な場合でも、イテレータはキーと値のペアを扱うため、it.key() と書く必要があります。

コード例

#include <QCoreApplication>
#include <QMap>
#include <QDebug>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QMap<QString, int> myMap;
    myMap["apple"] = 1;
    myMap["banana"] = 2;
    myMap["cherry"] = 3;

    qDebug() << "--- QMap::begin() / QMap::end() を使った反復 ---";
    for (QMap<QString, int>::const_iterator it = myMap.constBegin(); it != myMap.constEnd(); ++it) {
        qDebug() << "Key: " << it.key() << ", Value: " << it.value();
    }
    // `auto` キーワードを使えば型宣言を簡略化できます (C++11以降)
    for (auto it = myMap.constBegin(); it != myMap.constEnd(); ++it) {
        qDebug() << "Key (auto): " << it.key() << ", Value (auto): " << it.value();
    }

    return a.exec();
}

Javaスタイルイテレータ (QMapIterator) を使用する

Qtは、Javaプログラミング言語のイテレータに似た「Javaスタイルイテレータ」も提供しています。これは、hasNext()next() メソッドを持つオブジェクト指向のアプローチです。

利点

  • 前方・後方への移動
    toBack(), previous(), findNext(), findPrevious() などのメソッドを提供し、より高度なナビゲーションが可能です。
  • シンプルで高レベルなAPI
    while (it.hasNext()) { it.next(); ... } という構文は、一部の開発者にとって直感的です。

欠点

  • 読み取り専用/変更可能の分離
    マップを読み取り専用で反復処理したい場合は QMapIterator を、マップを修正したい場合は QMutableMapIterator を使用する必要があります。
  • 効率がわずかに低い
    STLスタイルイテレータに比べてわずかにオーバーヘッドがあります。

コード例

#include <QCoreApplication>
#include <QMap>
#include <QDebug>
#include <QMapIterator> // QMapIterator のために必要

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QMap<QString, int> myMap;
    myMap["apple"] = 1;
    myMap["banana"] = 2;
    myMap["cherry"] = 3;

    qDebug() << "--- QMapIterator を使った反復 ---";
    QMapIterator<QString, int> it(myMap);
    while (it.hasNext()) {
        it.next(); // 次の要素に進む
        qDebug() << "Key: " << it.key() << ", Value: " << it.value();
    }

    // 逆方向への反復 (QMapIteratorの機能)
    qDebug() << "\n--- QMapIterator を使った逆方向への反復 ---";
    it.toBack(); // イテレータをマップの末尾に移動
    while (it.hasPrevious()) {
        it.previous(); // 前の要素に進む
        qDebug() << "Key: " << it.key() << ", Value: " << it.value();
    }

    return a.exec();
}

Qt 5.10 以降: QMap::keyValueBegin() / QMap::keyValueEnd() を使用する

Qt 5.10以降では、QMap::keyValueBegin()QMap::keyValueEnd() という新しいSTLスタイルイテレータが導入されました。これらは、operator*() をデリファレンスすると std::pair<const Key, T> (または const_key_value_iterator の場合は std::pair<const Key, const T>) を返すため、C++17の構造化束縛と非常に相性が良く、キーと値の両方にアクセスしながらレンジベースforループを使用できます。

利点

  • 効率的
    一時的なコピーを生成しません。
  • C++17構造化束縛との相性
    非常に簡潔で現代的なC++の記述が可能です。

欠点

  • キー変更不可
    イテレータはキーを const として扱うため、キーを変更することはできません。
  • Qt 5.10以降のバージョンに限定
    古いQtバージョンでは使用できません。

コード例 (C++17以降)

#include <QCoreApplication>
#include <QMap>
#include <QDebug>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QMap<QString, int> myMap;
    myMap["apple"] = 1;
    myMap["banana"] = 2;
    myMap["cherry"] = 3;

    qDebug() << "--- QMap::keyValueBegin() を使った反復 (C++17 構造化束縛) ---";
    // Qt 6.4 以降では QMap::asKeyValueRange() が推奨されます
    // Qt 5.10-6.3 では keyValueBegin()/keyValueEnd() を使用
    for (auto it = myMap.keyValueBegin(); it != myMap.keyValueEnd(); ++it) {
        qDebug() << "Key: " << it->first << ", Value: " << it->second;
    }

    // C++17 構造化束縛 (Qt 6.4以降の asKeyValueRange() と組み合わせて使うとより自然)
    // Qt 5.10-6.3 で構造化束縛を使いたい場合は、
    // keyValueBegin/End を利用する簡単なラッパー関数を自作するか、
    // StackOverflowなどで紹介されているテクニックを使う必要があります。
    // 例: for (auto [key, value] : someWrapper(myMap)) { ... }
    // QMap::asKeyValueRange() は内部で keyValueBegin()/keyValueEnd() を使っています。
    // Qt 6.4以降:
    // for (auto [key, value] : myMap.asKeyValueRange()) {
    //     qDebug() << "Key: " << key << ", Value: " << value;
    // }

    return a.exec();
}

Qt 6.4 以降: QMap::asKeyValueRange() を使用する

Qt 6.4から導入された QMap::asKeyValueRange() は、keyValueBegin()keyValueEnd() をよりC++のイディオムに合うようにレンジベースforループで直接使用できるようにするヘルパー関数です。これはQt 5.10以降の keyValueBegin() と同様の機能を提供しますが、より現代的な構文で書けます。

利点

  • 簡潔性
    コードが最も簡潔で、読みやすいです。
  • 最も現代的なC++のイディオム
    C++17の構造化束縛と組み合わせて非常に自然なループが書けます。

欠点

  • Qt 6.4以降のバージョンに限定。
#include <QCoreApplication>
#include <QMap>
#include <QDebug>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QMap<QString, int> myMap;
    myMap["apple"] = 1;
    myMap["banana"] = 2;
    myMap["cherry"] = 3;

    qDebug() << "--- QMap::asKeyValueRange() を使った反復 (Qt 6.4 & C++17) ---";
    for (auto [key, value] : myMap.asKeyValueRange()) {
        qDebug() << "Key: " << key << ", Value: " << value;
    }

    return a.exec();
}
  • キーと値の両方を反復処理する場合
    • Qt 6.4以降 & C++17以降
      QMap::asKeyValueRange() と構造化束縛 (for (auto [key, value] : myMap.asKeyValueRange()))。これが最も現代的で推奨されます。
    • Qt 5.10-6.3 & C++17以降
      QMap::keyValueBegin() / QMap::keyValueEnd()it->first/it->second (for (auto it = myMap.keyValueBegin(); it != myMap.keyValueEnd(); ++it))。
    • Qt 5.9以前、またはC++11以前
      QMap::begin() / QMap::end()it.key() / it.value() (for (auto it = myMap.begin(); it != myMap.end(); ++it))。
    • Javaスタイルを好む場合
      QMapIterator
  • キーのみを反復処理する場合
    • 推奨
      QMap::keys() とレンジベースforループ (for (const auto& key : myMap.keys()))。コードが簡潔で分かりやすいため、特別なパフォーマンス要件がない限りこれがベストです。
    • 低レベルな制御が必要な場合
      QMap::keyBegin()keyEnd() (STLスタイル)。