1

I have a understanding-problem why following code does not store any QString-Objects into my QList

QMap<QString, QList<QString> >map;
map = QMap<QString, QList<QString> >();
map.insert("eins", QList<QString>());
QList<QString> listInMap = map["eins"];
listInMap.append("test1");
listInMap.append("test2");
QList<QString> copyOfListInMap = map.value("eins");
qDebug() << copyOfListInMap.count();

Output: 0

László Papp
  • 51,870
  • 39
  • 111
  • 135

2 Answers2

2

The reason is simple: copy on write, aka. implicit sharing

QList<QString> listInMap = map["eins"];

At this point, you have not yet got a hard copy, only a "reference". That is not fair in the standard C++ sense, but imagine it as a "shallow copy". However, when you start appending in here, the list will copied and the original will left empty. It is because QList is implemented the way that is CoW (copy-on-write).

listInMap.append("test1");
listInMap.append("test2");

On a side note, you may wish to take a look at QStringList. While it inherits QList, it also has some additional convenience methods.

Now, you may be asking: How am I supposed to fill my map in, then?.

Multi map

I would personally suggest to use QMultiMap or at least QMap with insertMulti.

main.cpp

#include <QMap>
#include <QDebug>
#include <QString>

int main()
{
    QMultiMap<QString, QString> map;
    map.insert("eins", "test1");
    map.insert("eins", "test2");
    qDebug() << map.count();
    return 0;
}

main.pro

TEMPLATE = app
TARGET = main
QT = core
SOURCES += main.cpp

Build and Run

qmake && make && ./main

Output

2

Single map

If you stick to the current approach, I would suggest to either append the value into a new QStringList with which you will overwrite the value, or hold a reference to the exact same list.

Having said that, in your case, it looks a bit overkill to even consider an external storage for insertion. You ought to do that right away in my humble opinion.

main.cpp

#include <QMap>
#include <QDebug>
#include <QString>

int main()
{
    QMap<QString, QStringList> map;
    map.insert("eins", QStringList{"test1", "test2"});
    qDebug() << map.value("eins").count();
    return 0;
}

main.pro

TEMPLATE = app
TARGET = main
QT = core
CONFIG += c++11
SOURCES += main.cpp

Build and Run

qmake && make && ./main

Output

2
László Papp
  • 51,870
  • 39
  • 111
  • 135
  • Thank you for your effort. I will research about the implicit sharing - i think that contains the key-facts which I need for the bigger picture about Qt. Currently, I get a slight idea that only one "real instance" can exists of this listed classes of qt: http://doc-snapshot.qt-project.org/qt5-5.4/implicit-sharing.html So i cannot have multiple pointer to one unique instance to access/modify it. The only thing what I don't understand is, why it work with the usage of references. But I think within the next hour the things get clear for me :) Greatly appricate for your help lpapp! – blackworker Dec 23 '14 at 17:23
  • @blackworker: because in that case you do not create a shallow copy. You have only got a reference. In fact, it does not matter whether it is CoW or value copy, you only need a reference for such cases. But then again, I think you should not use an external variable for such simple cases in the first place. See my 3-4 lines above how much easier it is than your original "messy" code. :) – László Papp Dec 23 '14 at 17:34
  • @lpapp It's all true, but in this case I think the problem is not that. The solution is the one that described by Andrey. – p.i.g. May 29 '15 at 17:33
1

According to the documentation your sample should be changed as follow:

QMap<QString, QList<QString> >map;
QList<QString> & listInMap = map["eins"]; // use reference here
listInMap.append("test1");
listInMap.append("test2");
QList<QString> copyOfListInMap = map.value("eins");
qDebug() << copyOfListInMap.count();
Andrii
  • 1,788
  • 11
  • 20
  • That solves actual my problem, thank you Andrey! But i do not understand why it won't work if i use a pointer, and not a reference. Furthermore I've also got no compiler warning about that? – blackworker Dec 23 '14 at 16:52
  • @blackworker: Because of CoW, as lpapp has described in his answer – Andrii Dec 23 '14 at 17:01