Неправильное поведение цикла в C ++ и Qt 6.2

Прежде всего, я полный новичок в C ++ и Qt, и я использую Qt 6.2 и C ++ 11. Это код, с которым у меня проблема:

      QSet<QList<QString>> listSet;
for(int i = 0; i < 10; i++)
{
    QList<QString> myList;
    for(int r = 0; r < 10; r++)
    {
        myList << "Item" + QString::number(r);
    }
    listSet.insert(myList);
}

qInfo() << listSet.count();

Я ожидал, что получу «10», но вместо этого получил «1». Я изменил код на этот, и он устранил проблему, но я просто не могу обдумать это:

      QSet<QList<QString>> listSet;
for(int i = 0; i < 10; i++)
{
    QList<QString> myList;
    myList << "default" + QString::number(i);
    for(int r = 0; r < 10; r++)
    {
        myList << "Item" + QString::number(r);
    }
    listSet.insert(myList);
}

qInfo() << listSet.count();

Я хочу знать, почему C ++ так себя ведет.

3 ответа

представляет собой набор уникальных объектов. Первый отрезанный код производит 10 одинаковых друг другу объектов. Таким образом, QSetполучает только один уникальный объект: выводит 1.

Второй фрагмент делает не равным myListобъектов, они отличаются первыми элементами списка, и qInfo() << listSet.count();выходы 10.

Думать об этом:

      using StringList = QList<QString>;
using SetOfStringLists = QSet< StringList >;

Итак, вы определяете набор из списка строк.

Однако все списки, которые вы создаете во внутреннем цикле, абсолютно одинаковы.

Поэтому в наборе останется только один! На самом деле это ожидаемое поведение.

Когда вы добавили изменение

      myList << "default" + QString::number(i);

затем вы сделали каждый добавленный элемент уникальным, поскольку iнаходится во внешнем цикле!

Я скомпилировал и запустил ваш первый пример, измененный, как показано ниже.

      #include <QSet>
#include <QList>
#include <QDebug>

int main() 
{
QSet<QList<QString>> listSet;
for(int i = 0; i < 10; i++)
{
    QList<QString> myList;
    //myList << "default" + QString::number(i);
    for(int r = 0; r < 10; r++)
    {
        myList << "Item" + QString::number(r);
    }
    listSet.insert(myList);
    qInfo() << myList;
}
qInfo() << listSet.count();
}

и он выводит

      $ ./testqt
("Item0", "Item1", "Item2", "Item3", "Item4", "Item5", "Item6", "Item7", "Item8", "Item9")
("Item0", "Item1", "Item2", "Item3", "Item4", "Item5", "Item6", "Item7", "Item8", "Item9")
("Item0", "Item1", "Item2", "Item3", "Item4", "Item5", "Item6", "Item7", "Item8", "Item9")
("Item0", "Item1", "Item2", "Item3", "Item4", "Item5", "Item6", "Item7", "Item8", "Item9")
("Item0", "Item1", "Item2", "Item3", "Item4", "Item5", "Item6", "Item7", "Item8", "Item9")
("Item0", "Item1", "Item2", "Item3", "Item4", "Item5", "Item6", "Item7", "Item8", "Item9")
("Item0", "Item1", "Item2", "Item3", "Item4", "Item5", "Item6", "Item7", "Item8", "Item9")
("Item0", "Item1", "Item2", "Item3", "Item4", "Item5", "Item6", "Item7", "Item8", "Item9")
("Item0", "Item1", "Item2", "Item3", "Item4", "Item5", "Item6", "Item7", "Item8", "Item9")
("Item0", "Item1", "Item2", "Item3", "Item4", "Item5", "Item6", "Item7", "Item8", "Item9")
1

Когда вы закомментируете добавленную вами строку, она станет

      $ ./testqt
("default0", "Item0", "Item1", "Item2", "Item3", "Item4", "Item5", "Item6", "Item7", "Item8", "Item9")
("default1", "Item0", "Item1", "Item2", "Item3", "Item4", "Item5", "Item6", "Item7", "Item8", "Item9")
("default2", "Item0", "Item1", "Item2", "Item3", "Item4", "Item5", "Item6", "Item7", "Item8", "Item9")
("default3", "Item0", "Item1", "Item2", "Item3", "Item4", "Item5", "Item6", "Item7", "Item8", "Item9")
("default4", "Item0", "Item1", "Item2", "Item3", "Item4", "Item5", "Item6", "Item7", "Item8", "Item9")
("default5", "Item0", "Item1", "Item2", "Item3", "Item4", "Item5", "Item6", "Item7", "Item8", "Item9")
("default6", "Item0", "Item1", "Item2", "Item3", "Item4", "Item5", "Item6", "Item7", "Item8", "Item9")
("default7", "Item0", "Item1", "Item2", "Item3", "Item4", "Item5", "Item6", "Item7", "Item8", "Item9")
("default8", "Item0", "Item1", "Item2", "Item3", "Item4", "Item5", "Item6", "Item7", "Item8", "Item9")
("default9", "Item0", "Item1", "Item2", "Item3", "Item4", "Item5", "Item6", "Item7", "Item8", "Item9")
10

QSet основан на хеше

QSet основан на хеше; если хэши двух элементов равны, то QSet не будет открывать новое пространство. И метод расчета хэша QList основан на его элементах.

Другими словами, если два QList имеют одинаковые элементы, они будут иметь одинаковый хэш. И, поскольку у них одинаковый хэш, QSet не откроет новое пространство.

Из вашего первого кода: каждый qlist имеет одинаковые элементы с:

      {"Item0","Item1","Item2","Item3",....}

потому что у них одинаковые элементы, поэтому у них будет одинаковый хэш. В конце концов, QSet будет иметь только один элемент.

Но во втором коде каждый qlist имеет другой хеш:

      qlist0: {"default0", "Item0", "Item1", ...}
qlist1: {"default1", "Item0", "Item1", ...}
...
...

Как видите, первый элемент каждого qlist отличается, поэтому у них будет разный хэш, и QSet откроет новое пространство для каждого qlist.

Другие вопросы по тегам