I want to build up a map of devices such that the map contains:
QString 'DeviceID' and QVector 'Command List'
Currently I have the QMap as follows:
QMap<QString, QVector<QString> *> devices;
QVector<QString> *pCommands= new QVector<QString>;
// :
// Fill pCommands with lots of data here
// :
devices.insert(RadioID, pCommands);
But I am wondering if this is actually any better then:
QMap<QString, QVector<QString>> devices;
QVector<QString> commands;
// :
// Fill commands with lots of data here
// :
devices.insert(RadioID, commands);
I am sure that I read somewhere that Qt does something quite efficient when copying data. I am not seeing many people using pointers with Qt and it seems messy that I have to go through the QMap deleting all the QVector's at the end...
I am using c++11, so maybe some kind of move semantic may work here?
EDIT I have modified the comments in the code to show that the vector is not empty. Also I would state that I do not need to change the data once it is stored.
There is no reason to consider manually allocating the vectors to be better.
Sure, you only need to copy a pointer, rather than a vector, but an empty vector is still quite fast to copy. The biggest gain of storing objects rather than pointers is that you don't need to do manual memory management.
I am using c++11, so maybe some kind of move semantic may work here?
If QMap::insert
supports move semantics, and if QVector
is move-constructible like their standard library counterparts, then you could indeed move the vector into the map. But moving an empty vector is just as fast as copying.
If QMap
has an emplace
like function std::map
does, then you could even construct the vector in-place without even a move.
I'm not familiar with Qt, though so you'll need to verify those details from the documentation. Whether Qt supports move semantics doesn't change the fact that manual memory management is a pain.
Edit: according to the documentation QVector
appears to be movable, but QMap
does not support move semantics. However, as Arpegius and the documentation point out, QVector
does copy-on-write optimization, so as long as the copied vector is not modified, then the data won't be copied. None of this matters really, when copying an empty vector.
Edit again
If the added vectors are full of data, then copying is indeed quite expensive unless it remains unmodified. Moving would remedy that, but QMap
appears not to support that. There is another trick, though: Insert an empty vector, and then swap
the full vector with the empty one in the map.
The simplest and pretty much idiomatic way to do it would be:
QMap<QString, QVector<QString>> devices;
// Get the vector constructed in the map itself.
auto & commands = devices[RadioID];
// Fill commands with lots of data here - a bit faster
commands.resize(2);
commands[0] = "Foo";
commands[1] = "Bar";
// Fill commands with lots of data here - a bit slower
commands.append("Baz");
commands.append("Fan");
You'll see this pattern often in Qt and other code, and it's the simplest way to do it that works equally well on C++98 and C++11 :)
This way you're working on the vector that's already in the map. The vector itself is never copied. The members of the vector are copied, but they are implicitly shared, so copying is literally a pointer copy and an atomic reference count increment.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.