Qt QList::count() テンプレート引数AT=Tの秘密:実用例で学ぶ

2025-06-06

このメソッドは、QtのコンテナクラスであるQListが提供するオーバーロードされたcount()関数の一つです。

QListについて

QList<T>は、C++のテンプレートクラスで、リスト(動的配列)を提供します。Tはリストに格納される要素の型を示します。内部的には、要素へのポインタの配列として表現されることが多く、インデックスによる高速なアクセスや、リストの両端での高速な挿入・削除が特徴です。

count()メソッドの役割

count()メソッドには主に2つのオーバーロードがあります。

  1. 引数なしの count(): qsizetype QList::count() const これはリストに含まれる要素の総数を返します。size()length()メソッドと同じ結果を返します。

    例:

    QList<QString> list;
    list << "Apple" << "Banana" << "Cherry";
    qsizetype totalCount = list.count(); // totalCount は 3 になります
    


operator==() が定義されていない、または適切に機能しない

エラーの原因
QList::count(value) メソッドは、リスト内の各要素が value と等しいかどうかを比較するために operator==() を使用します。もしリストの要素の型 T またはテンプレートパラメータ AT で渡される型に対して operator==() が定義されていない場合、コンパイルエラーが発生します。また、定義されていても意図しない比較ロジックになっている場合、予期しない結果(常に0や誤ったカウント数)が返されることがあります。


カスタムクラス MyObject のリストがあり、MyObjectoperator==() がオーバーロードされていない場合:

class MyObject {
public:
    int id;
    QString name;
    // operator==() が定義されていない
};

QList<MyObject> myObjects;
MyObject obj1 = {1, "Test"};
myObjects.append(obj1);
myObjects.append({2, "Another"});
myObjects.append(obj1); // 同じオブジェクトを再度追加

qsizetype count = myObjects.count(obj1); // コンパイルエラー、または期待通りの動作をしない

トラブルシューティング

  • ポインタの比較に注意する
    QList<MyObject*> のようにポインタのリストの場合、デフォルトの operator==() はポインタのアドレスを比較します。オブジェクトの中身を比較したい場合は、ポインタをデリファレンスして中身を比較するか、カスタム比較関数を使用する必要があります。
    QList<MyObject*> myObjectPointers;
    MyObject *obj1_ptr = new MyObject{1, "Test"};
    MyObject *obj2_ptr = new MyObject{2, "Another"};
    myObjectPointers.append(obj1_ptr);
    myObjectPointers.append(obj2_ptr);
    myObjectPointers.append(new MyObject{1, "Test"}); // 別のアドレスに同じ内容のオブジェクト
    
    // アドレスで比較されるため、obj1_ptr と同じアドレスを持つものしかカウントされない
    qsizetype count_ptr = myObjectPointers.count(obj1_ptr); // 1 が返る (obj1_ptr自身のみ)
    
    // オブジェクトの中身でカウントしたい場合(count()では直接できない)
    qsizetype content_count = 0;
    MyObject target_obj = {1, "Test"};
    for (MyObject *obj : myObjectPointers) {
        if (*obj == target_obj) { // MyObject::operator==() を利用
            content_count++;
        }
    }
    // content_count は 2 になる
    
  • カスタム型に operator==() をオーバーロードする
    QList に格納するカスタムクラス(T)や、count() に渡す値の型(AT)に対して、適切に operator==() を定義します。
    class MyObject {
    public:
        int id;
        QString name;
    
        bool operator==(const MyObject &other) const {
            return (id == other.id && name == other.name);
        }
    };
    
    QList<MyObject> myObjects;
    MyObject obj1 = {1, "Test"};
    myObjects.append(obj1);
    myObjects.append({2, "Another"});
    myObjects.append(obj1);
    
    qsizetype count = myObjects.count(obj1); // これで期待通り 2 が返ります
    

型の不一致

エラーの原因
QList の要素型 Tcount() に渡す値の型 AT が互換性がない場合、コンパイルエラーが発生します。


QList<int> に対して QString を検索しようとする場合など。

QList<int> numbers;
numbers << 1 << 2 << 3;

// numbers.count("2"); // コンパイルエラー: int と QString は比較できない

トラブルシューティング

  • count() に渡す引数の型が QList の要素型と一致しているか、または暗黙的に変換可能であり、かつ operator==() が適切に定義されているかを確認します。

パフォーマンスの問題(大規模なリストの場合)

エラーの原因
QList::count(value) は、指定された値と一致する要素を数えるために、リストのすべての要素を最初から最後まで順に走査します。リストが非常に大きい場合、この操作は時間がかかる可能性があります(O(N) の時間計算量)。特に、ループ内で何度も count() を呼び出すと、アプリケーションの応答性が低下する可能性があります。


巨大なログファイルの行を QList<QString> に読み込み、特定のキーワードの出現頻度を何度も計算する場合。

QList<QString> largeLog;
// ... 数十万行のログを largeLog に読み込む ...

// ユーザーがキーワードを入力するたびに count() を呼ぶ
QString keyword = getUserInput();
qsizetype occurrences = largeLog.count(keyword); // 遅い可能性がある

トラブルシューティング

  • マルチスレッド化
    非常に巨大なリストで、かつカウント処理がボトルネックになっている場合、処理を複数のスレッドに分割して並列実行することも検討できますが、これは複雑さを増します。
  • 自前のループで最適化する
    特定の条件でカウントしたい場合(operator==() では表現できない複雑な条件など)や、途中で処理を中断したい場合、自前のループを使用する方が柔軟性があります。
    qsizetype customCount = 0;
    for (const MyObject &obj : myObjects) {
        if (obj.id > 100 && obj.name.startsWith("Prefix")) {
            customCount++;
        }
    }
    
  • 異なるデータ構造を検討する
    頻繁に特定の要素の出現回数を取得する必要がある場合、QMap<T, int> (または QHash<T, int>) のように、要素をキーとし、その出現回数を値とするマップを使用することを検討します。これにより、要素の追加/削除時にマップを更新する手間はかかりますが、カウントの取得はO(1)または平均O(1)に高速化されます。
    QMap<QString, qsizetype> keywordCounts;
    // ログを読み込む際にマップを更新
    for (const QString &line : largeLog) {
        // 例: 各行のキーワードを抽出してマップを更新
        if (line.contains("Error")) {
            keywordCounts["Error"]++;
        } else if (line.contains("Warning")) {
            keywordCounts["Warning"]++;
        }
    }
    
    // カウントの取得は高速
    qsizetype errorCount = keywordCounts.value("Error", 0);
    
  • 必要に応じてキャッシュする
    もし頻繁に同じ値をカウントする必要がある場合、一度カウントした結果をキャッシュしておき、リストが変更されたときのみ再計算するようにします。

エラーの原因
QList<MyObject*> のようなポインタのリストで、リストに追加した後にポインタが指すオブジェクトが解放されたり、無効なメモリ領域を指すようになったりした場合、count() が無効なメモリを比較しようとしてクラッシュ(セグメンテーションフォールトなど)する可能性があります。


QList<MyObject*> myObjectPointers;
{
    MyObject obj; // ローカル変数
    myObjectPointers.append(&obj); // ローカル変数のアドレスをリストに追加
} // obj はここでスコープを抜けて破壊される

// myObjectPointers の要素は無効なアドレスを指している
// myObjectPointers.count(&obj); // クラッシュする可能性が高い
  • nullptr チェック
    ポインタのリストを扱う場合、count() を呼び出す前に、あるいは operator==() の実装内で nullptr チェックを行うことで、クラッシュを防げる場合があります。
  • オブジェクトの寿命管理を徹底する
    生のポインタを使用する場合、リストに格納されているオブジェクトがリストの生存期間中、有効であることを常に保証する必要があります。
  • スマートポインタの使用
    QSharedPointerstd::shared_ptr など、スマートポインタを使用してオブジェクトのライフサイクルを管理します。これにより、ポインタが無効なメモリを指すことを防ぎ、オブジェクトが不要になったときに自動的に解放されます。
    QList<QSharedPointer<MyObject>> mySharedObjects;
    QSharedPointer<MyObject> obj1 = QSharedPointer<MyObject>::create(1, "Test");
    mySharedObjects.append(obj1);
    mySharedObjects.append(QSharedPointer<MyObject>::create(2, "Another"));
    mySharedObjects.append(obj1); // 同じ QSharedPointer を再度追加
    
    // count() は QSharedPointer の operator== を使用し、中身を比較するため、適切に動作する
    qsizetype count = mySharedObjects.count(obj1); // 2 が返る
    


このメソッドは、QList内に特定の要素がいくつ存在するかを数えるために使用されます。ここでは、様々なデータ型での使用例と、注意点を含めた例を示します。

基本的なデータ型 (int, QString など) の場合

intQString のようなQtが提供する基本的なデータ型は、すでにoperator==()が適切に定義されているため、そのままcount()を使用できます。

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

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

    // --- int 型の QList ---
    QList<int> intList;
    intList << 10 << 20 << 10 << 30 << 20 << 10;

    qDebug() << "intList:" << intList;
    qDebug() << "Count of 10:" << intList.count(10); // 10 が 3 回出現
    qDebug() << "Count of 20:" << intList.count(20); // 20 が 2 回出現
    qDebug() << "Count of 50:" << intList.count(50); // 50 は出現しない (0)

    // --- QString 型の QList ---
    QList<QString> stringList;
    stringList << "Apple" << "Banana" << "Apple" << "Orange" << "apple"; // "apple" は小文字

    qDebug() << "\nstringList:" << stringList;
    qDebug() << "Count of 'Apple':" << stringList.count("Apple"); // 'Apple' が 2 回出現
    qDebug() << "Count of 'apple':" << stringList.count("apple"); // 'apple' が 1 回出現 (大文字小文字を区別する)
    qDebug() << "Count of 'Grape':" << stringList.count("Grape"); // 'Grape' は出現しない (0)

    return a.exec();
}

実行結果例

intList: QList(10, 20, 10, 30, 20, 10)
Count of 10: 3
Count of 20: 2
Count of 50: 0

stringList: QList("Apple", "Banana", "Apple", "Orange", "apple")
Count of 'Apple': 2
Count of 'apple': 1
Count of 'Grape': 0

カスタムクラスの場合

QListにカスタムクラスのオブジェクトを格納し、そのオブジェクトをcount()で数えるには、カスタムクラスにoperator==()をオーバーロードする必要があります。

#include <QCoreApplication>
#include <QList>
#include <QString>
#include <QDebug>

// カスタムクラスの定義
class Book
{
public:
    QString title;
    QString author;
    int year;

    Book(const QString &title = "", const QString &author = "", int year = 0)
        : title(title), author(author), year(year) {}

    // 重要: operator==() のオーバーロード
    // QList::count() がオブジェクトを比較するために必要
    bool operator==(const Book &other) const
    {
        // 全てのメンバーが一致する場合に true を返す
        return (title == other.title &&
                author == other.author &&
                year == other.year);
    }

    // デバッグ出力用のストリーム演算子 (オプションだが便利)
    friend QDebug operator<<(QDebug debug, const Book &book)
    {
        QDebugStateSaver saver(debug);
        debug.nospace() << "Book(Title: '" << book.title << "', Author: '"
                        << book.author << "', Year: " << book.year << ")";
        return debug;
    }
};

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

    QList<Book> library;
    library << Book("The Lord of the Rings", "J.R.R. Tolkien", 1954);
    library << Book("Pride and Prejudice", "Jane Austen", 1813);
    library << Book("The Lord of the Rings", "J.R.R. Tolkien", 1954); // 同じ本を再度追加
    library << Book("1984", "George Orwell", 1949);
    library << Book("The Lord of the Rings", "J.R.R. Tolkien", 1954); // 同じ本を再度追加

    qDebug() << "Library:" << library;

    // 検索したい本を作成
    Book searchBook("The Lord of the Rings", "J.R.R. Tolkien", 1954);

    // count() を使用して検索
    qsizetype count = library.count(searchBook);

    qDebug() << "\nSearching for:" << searchBook;
    qDebug() << "Count of this book in library:" << count; // 期待値: 3

    // 存在しない本の検索
    Book nonExistentBook("Unknown Book", "Unknown Author", 2000);
    qsizetype nonExistentCount = library.count(nonExistentBook);
    qDebug() << "Count of 'Unknown Book':" << nonExistentCount; // 期待値: 0

    return a.exec();
}

実行結果例

Library: QList(Book(Title: 'The Lord of the Rings', Author: 'J.R.R. Tolkien', Year: 1954), Book(Title: 'Pride and Prejudice', Author: 'Jane Austen', Year: 1813), Book(Title: 'The Lord of the Rings', Author: 'J.R.R. Tolkien', Year: 1954), Book(Title: '1984', Author: 'George Orwell', Year: 1949), Book(Title: 'The Lord of the Rings', Author: 'J.R.R. Tolkien', Year: 1954))

Searching for: Book(Title: 'The Lord of the Rings', Author: 'J.R.R. Tolkien', Year: 1954)
Count of this book in library: 3
Count of 'Unknown Book': 0

ポインタのリストの場合 (QList<MyClass*>)

QList<MyClass*> のようにポインタのリストを使用する場合、count() メソッドはデフォルトでポインタのアドレスを比較します。オブジェクトの中身で比較したい場合は、count() は直接使えず、手動でループを回すか、QSharedPointer などのスマートポインタを検討する必要があります。

#include <QCoreApplication>
#include <QList>
#include <QString>
#include <QDebug>

class Animal
{
public:
    QString name;
    int age;

    Animal(const QString &name = "", int age = 0) : name(name), age(age) {}

    // オブジェクトの中身を比較するための operator==()
    bool operator==(const Animal &other) const
    {
        return (name == other.name && age == other.age);
    }

    friend QDebug operator<<(QDebug debug, const Animal &animal)
    {
        QDebugStateSaver saver(debug);
        debug.nospace() << "Animal(Name: '" << animal.name << "', Age: " << animal.age << ")";
        return debug;
    }
};

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

    QList<Animal*> animalPointers;
    Animal *dog1 = new Animal("Dog", 3);
    Animal *cat1 = new Animal("Cat", 2);
    Animal *dog2 = new Animal("Dog", 3); // dog1 と内容は同じだが、別のアドレス

    animalPointers << dog1 << cat1 << dog2;

    qDebug() << "Animal Pointers List (Addresses):" << animalPointers; // アドレスが出力される

    // --- 例1: ポインタのアドレスを比較する場合 ---
    // count() はポインタのアドレスが一致するかどうかを比較する
    qsizetype countDog1Address = animalPointers.count(dog1);
    qDebug() << "Count of dog1 (by address):" << countDog1Address; // 1 (dog1 自身のみ)

    // dog2 は dog1 とアドレスが異なるため、カウントされない
    qsizetype countDog2Address = animalPointers.count(dog2);
    qDebug() << "Count of dog2 (by address):" << countDog2Address; // 1 (dog2 自身のみ)

    // --- 例2: オブジェクトの中身を比較したい場合 ---
    // QList::count() は直接ポインタの指す中身を比較するオーバーロードを持たない
    // そのため、手動でループを回す必要がある
    qsizetype countSameContentDogs = 0;
    Animal targetDog("Dog", 3); // 検索したい対象のオブジェクト内容

    for (Animal *animalPtr : animalPointers) {
        if (animalPtr && *animalPtr == targetDog) { // ポインタが有効で、かつ中身が一致する場合
            countSameContentDogs++;
        }
    }
    qDebug() << "Count of dogs with same content ('Dog', 3):" << countSameContentDogs; // 2 (dog1とdog2)

    // メモリ解放 (ポインタのリストの場合、手動で解放が必要)
    qDeleteAll(animalPointers);

    return a.exec();
}

実行結果例

Animal Pointers List (Addresses): QList(0x...dog1_addr..., 0x...cat1_addr..., 0x...dog2_addr...)
Count of dog1 (by address): 1
Count of dog2 (by address): 1
Count of dogs with same content ('Dog', 3): 2

ポインタリストの注意点

  • 推奨されるのはQSharedPointerのようなスマートポインタを使用することです。QSharedPointeroperator==()をオーバーロードしており、ポインタが指すオブジェクトの中身を比較します。
  • ポインタが指すオブジェクトが途中で削除されたり、無効な状態になったりすると、未定義の動作やクラッシュの原因になります。
  • 生ポインタのQListを使用する場合、オブジェクトのライフサイクル管理(newdelete)はプログラマの責任です。

QSharedPointer を使用した場合

スマートポインタであるQSharedPointerを使用すると、ポインタのリストでもオブジェクトの中身を比較してcount()できるようになります。

#include <QCoreApplication>
#include <QList>
#include <QSharedPointer>
#include <QString>
#include <QDebug>

class Toy
{
public:
    QString type;
    QString color;

    Toy(const QString &type = "", const QString &color = "")
        : type(type), color(color) {}

    // オブジェクトの中身を比較するための operator==()
    bool operator==(const Toy &other) const
    {
        return (type == other.type && color == other.color);
    }

    friend QDebug operator<<(QDebug debug, const Toy &toy)
    {
        QDebugStateSaver saver(debug);
        debug.nospace() << "Toy(Type: '" << toy.type << "', Color: '" << toy.color << "')";
        return debug;
    }
};

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

    QList<QSharedPointer<Toy>> toys;
    QSharedPointer<Toy> doll1 = QSharedPointer<Toy>::create("Doll", "Pink");
    QSharedPointer<Toy> car1 = QSharedPointer<Toy>::create("Car", "Red");
    QSharedPointer<Toy> doll2 = QSharedPointer<Toy>::create("Doll", "Pink"); // doll1 と内容は同じだが別オブジェクト

    toys << doll1 << car1 << doll2 << doll1; // doll1 を再度追加

    qDebug() << "Toys (QSharedPointer):" << toys;

    // QSharedPointer は operator==() がオーバーロードされており、
    // 指すオブジェクトの中身を比較する
    qsizetype countPinkDoll = toys.count(doll1); // doll1 と中身が同じものをカウント

    qDebug() << "\nSearching for:" << doll1;
    qDebug() << "Count of Pink Dolls (using QSharedPointer::count):" << countPinkDoll; // 期待値: 3 (doll1が2つ、doll2が1つ)

    // 別に作成した同じ内容のQSharedPointerでもカウント可能
    QSharedPointer<Toy> searchToy = QSharedPointer<Toy>::create("Doll", "Pink");
    qsizetype countViaNewPointer = toys.count(searchToy);
    qDebug() << "Count of Pink Dolls (using new QSharedPointer instance):" << countViaNewPointer; // 期待値: 3

    return a.exec();
}
Toys (QSharedPointer): QList(Toy(Type: 'Doll', Color: 'Pink'), Toy(Type: 'Car', Color: 'Red'), Toy(Type: 'Doll', Color: 'Pink'), Toy(Type: 'Doll', Color: 'Pink'))

Searching for: Toy(Type: 'Doll', Color: 'Pink')
Count of Pink Dolls (using QSharedPointer::count): 3
Count of Pink Dolls (using new QSharedPointer instance): 3


手動でのループ処理 (for ループ、範囲ベース for ループ)

最も基本的で柔軟な方法です。count() メソッドが内部で行っていることと本質的に同じですが、より複雑な条件や、パフォーマンスを考慮した最適化が必要な場合に直接制御できます。

利点

  • 特定の条件を満たす要素に対して追加の処理を行うことができる。
  • 途中でカウントを中断するなどの制御が可能。
  • operator==() 以外の複雑な比較ロジックを適用できる。

欠点

  • 単純なカウントには冗長になる。
  • コード量が増える。


#include <QCoreApplication>
#include <QList>
#include <QString>
#include <QDebug>

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

    QList<int> numbers;
    numbers << 10 << 20 << 10 << 30 << 20 << 10 << 40;

    int targetValue = 10;
    qsizetype count = 0;

    // 範囲ベース for ループ (C++11 以降)
    for (int num : numbers) {
        if (num == targetValue) {
            count++;
        }
    }
    qDebug() << "Count of" << targetValue << " (manual loop):" << count; // 3

    // 特定の条件でカウント (例: 20より大きい偶数)
    qsizetype evenGreaterThan20Count = 0;
    for (int num : numbers) {
        if (num > 20 && num % 2 == 0) {
            evenGreaterThan20Count++;
        }
    }
    qDebug() << "Count of even numbers greater than 20 (manual loop):" << evenGreaterThan20Count; // 30, 40 -> 2

    return a.exec();
}

STLアルゴリズム (std::count, std::count_if)

C++標準ライブラリの <algorithm> ヘッダには、コンテナの要素を数えるための汎用アルゴリズムが提供されています。QListstd::vector と同様のイテレータを提供しているため、これらのアルゴリズムと組み合わせて使用できます。

  • std::count_if(first, last, predicate): 指定された述語(ラムダ関数や関数オブジェクト)が true を返す要素の数を数えます。より複雑な条件でカウントしたい場合に非常に強力です。
  • std::count(first, last, value): 特定の値に一致する要素の数を数えます。QList::count(value) と同じ機能です。

利点

  • コードが簡潔になる。
  • ラムダ関数と組み合わせることで、非常に柔軟なカウント条件を記述できる。
  • C++標準に準拠しており、汎用性が高い。

欠点

  • Qt 独自の機能(QDebug 出力など)との連携は手動になる。
  • Qt の qsizetype ではなく、std::iterator_traits<InputIt>::difference_type に相当する型(通常は long int)を返すため、必要に応じて型変換が必要になる場合がある。


#include <QCoreApplication>
#include <QList>
#include <QString>
#include <QDebug>
#include <algorithm> // std::count, std::count_if を使用するため

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

    QList<QString> fruits;
    fruits << "Apple" << "Banana" << "Apple" << "Orange" << "apple";

    // --- std::count の使用 ---
    // QList の begin() と end() イテレータを使用
    qsizetype countApple = std::count(fruits.begin(), fruits.end(), QString("Apple"));
    qDebug() << "Count of 'Apple' (std::count):" << countApple; // 2

    // --- std::count_if の使用 (ラムダ関数で柔軟な条件) ---
    // 大文字小文字を区別せずに 'apple' をカウント
    qsizetype countAppleCaseInsensitive = std::count_if(fruits.begin(), fruits.end(),
                                                      [](const QString &s) {
                                                          return s.compare("apple", Qt::CaseInsensitive) == 0;
                                                      });
    qDebug() << "Count of 'apple' (case-insensitive, std::count_if):" << countAppleCaseInsensitive; // 3

    // 文字列長が5文字以上のフルーツをカウント
    qsizetype longFruitsCount = std::count_if(fruits.begin(), fruits.end(),
                                               [](const QString &s) {
                                                   return s.length() >= 5;
                                               });
    qDebug() << "Count of fruits with length >= 5 (std::count_if):" << longFruitsCount; // Apple, Banana, Orange -> 3

    return a.exec();
}

ハッシュマップ/マップによる頻度集計 (QHash, QMap)

もし、リスト内の各要素の出現回数を頻繁に取得する必要がある場合や、事前にすべての要素の出現回数を計算しておきたい場合は、ハッシュマップ (QHash) やマップ (QMap) を使用して頻度を事前集計するのが最も効率的です。

利点

  • 異なる種類の要素のカウントを同時に管理できる。
  • 一度集計すれば、その後のカウント取得は非常に高速(平均 O(1) または O(logN))。

欠点

  • リストの要素が変更されない場合にのみ有効。
  • リストに追加・削除があるたびにマップも更新する必要があるため、メンテナンスコストがかかる。


#include <QCoreApplication>
#include <QList>
#include <QString>
#include <QDebug>
#include <QHash> // ハッシュマップを使用

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

    QList<QString> dataList;
    dataList << "Red" << "Green" << "Blue" << "Red" << "Green" << "Red" << "Yellow";

    QHash<QString, qsizetype> counts; // 各文字列とその出現回数を格納するハッシュマップ

    // リストを一度走査して、各要素の出現回数を集計
    for (const QString &item : dataList) {
        counts[item]++; // QHash の operator[] はキーが存在しない場合にデフォルト値を挿入し、存在する場合は値を返す
    }

    qDebug() << "Original list:" << dataList;
    qDebug() << "All counts (using QHash):" << counts;

    // 後から特定の要素のカウントを取得するのは非常に高速
    qDebug() << "Count of 'Red':" << counts.value("Red", 0);     // 3
    qDebug() << "Count of 'Green':" << counts.value("Green", 0); // 2
    qDebug() << "Count of 'Orange':" << counts.value("Orange", 0); // 0 (存在しない場合はデフォルト値0)

    // カスタムクラスをキーにする場合は、そのクラスに QHash の要件(qHash と operator==)を満たす必要がある
    // (詳細は QHash のドキュメントを参照)

    return a.exec();
}
Original list: QList("Red", "Green", "Blue", "Red", "Green", "Red", "Yellow")
All counts (using QHash): QHash(("Blue", 1), ("Green", 2), ("Red", 3), ("Yellow", 1))
Count of 'Red': 3
Count of 'Green': 2
Count of 'Orange': 0
  • ポインタのリストでオブジェクトの中身を比較したいなら
    • QList<QSharedPointer<T>> を使用し、QList::count(shared_ptr_instance) を使うのが良いでしょう。
    • 生ポインタの場合、手動でループを回してデリファレンスして比較する必要があります。
  • 頻繁に各要素の出現回数を問い合わせる必要があるなら
    • QHash または QMap を使って事前に集計するのが最も効率的です。
  • operator==() では表現できない複雑な条件で数えたいなら
    • std::count_if (ラムダ関数と組み合わせる) が非常に強力です。
    • または、手動でのループ処理が柔軟性を提供します。
  • 単純に特定の値を数えるだけなら
    • QList::count(value) が最も簡潔で推奨されます。