blackworker
blackworker

Reputation: 13

Qt QList does not append local Objects

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

Upvotes: 1

Views: 1799

Answers (2)

L&#225;szl&#243; Papp
L&#225;szl&#243; Papp

Reputation: 53173

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

Upvotes: 2

Andrii
Andrii

Reputation: 1906

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

Upvotes: 1

Related Questions