Qt QMapのキーを効率的に反復処理:keyBegin()徹底解説
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::iterator
やQMap::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_iterator
は const
イテレータであるため、イテレータ自身を使って 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::iterator
とQMap::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
は内部的にキーをソートして格納するため、キーの型 Key
に operator<()
が定義されている必要があります。これが定義されていない場合、コンパイルエラーが発生します。
// 誤った例: 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
。
- Qt 6.4以降 & C++17以降
- キーのみを反復処理する場合
- 推奨
QMap::keys()
とレンジベースforループ (for (const auto& key : myMap.keys())
)。コードが簡潔で分かりやすいため、特別なパフォーマンス要件がない限りこれがベストです。 - 低レベルな制御が必要な場合
QMap::keyBegin()
とkeyEnd()
(STLスタイル)。
- 推奨