-1

First of all i'm a complete beginner in C++ and Qt and i'm using Qt 6.2 and C++11. This is the code that i have problem with:

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();

I was expecting that i would get the output of "10" but instead i got "1". I changed the code to this and it fixed the problem but i just can't wrap my head around it:

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();

i want to know why C++ is behaving like this.

A . R . B
  • 27
  • 5

3 Answers3

2

QSet is a collection of unique objects. The first code snipped produces 10 equal to each other myList objects. Thus, QSet gets only one unique myList object: qInfo() << listSet.count(); outputs 1.

The second snippet makes not equal myList objects, they differ by the first list items, and qInfo() << listSet.count(); outputs 10.

273K
  • 29,503
  • 10
  • 41
  • 64
0

Think about this:

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

So you are defining a set of a list of strings.

However all the lists you are creating in the inner loop are exactly the same.

Therefore the set will only keep one! This is actually the expected behavior.

When you added the change

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

then you made every item added unique since i is in the outer loop!

I did compile and run your first example modified as below

#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();
}

and it outputs

$ ./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

When you comment out that line you added, it becomes

$ ./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
0

QSet is based on hash

QSet is based on hash; if the hashes of the two items are equal, then the QSet will not open up a new space. And the hash calculation method of QList is based on its elements.

In other words, if two QList have the same elements, they will have the same hash. And, because they have the same hash, the QSet will not open up a new space.

From your first code: every qlist has the same elements with:

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

because they have the same elements, so they will have the same hash. In the end, the QSet will only have one element.

But, in your second code, every qlist has a different hash:

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

As you can see, every qlist's first element is different, therefore they will have different hash, and QSet will open up a new space for every qlist.

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
N0I0C0K
  • 47
  • 3