QMap 通过指针或值插入 QVector<QString>?

QMap insert QVector<QString> by pointer or value?

我想构建一个设备地图,该地图包含:

QString 'DeviceID' 和 QVector 'Command List'

目前我的QMap如下:

QMap<QString, QVector<QString> *> devices;

QVector<QString> *pCommands= new QVector<QString>;
//       :
// Fill pCommands with lots of data here
//       :
devices.insert(RadioID, pCommands);

但我想知道这是否真的更好:

QMap<QString, QVector<QString>> devices;

QVector<QString> commands;
//       :
// Fill commands with lots of data here
//       :
devices.insert(RadioID, commands);

我确信我在某处读到 Qt 在复制数据时做的事情非常有效。我没有看到很多人在 Qt 中使用指针,而且我必须通过 QMap 在最后删除所有 QVector 看起来很乱...

我使用的是 c++11,所以也许某种移动语义在这里起作用?

编辑 我修改了代码中的注释以表明向量不为空。 另外我要声明的是,我不需要在存储数据后更改它。

没有理由考虑手动分配向量更好。

当然,你只需要复制一个指针,而不是一个向量,但是一个空的向量复制起来还是很快的。存储对象而不是指针的最大好处是不需要手动进行内存管理。

I am using c++11, so maybe some kind of move semantic may work here?

如果 QMap::insert 支持移动语义,并且如果 QVector 像标准库对应物一样是可移动构造的,那么您确实可以将矢量移动到地图中。但是移动一个空向量和复制一样快。

如果 QMap 有一个像函数 std::map 那样的 emplace,那么你甚至可以在不移动的情况下就地构造向量。

我不熟悉 Qt,所以您需要从文档中验证这些细节。 Qt是否支持移动语义并不能改变手动内存管理很痛苦的事实。


编辑:根据documentation QVector 似乎是可移动的,但QMap 不支持移动语义。但是,正如 Arpegius 和文档指出的那样,QVector 会进行写时复制优化,因此只要复制的向量未被修改,就不会复制数据。 None 在复制空向量时,这确实很重要。


再次编辑

如果添加的向量都是数据,那么复制确实是相当昂贵的,除非它保持不变。搬家可以解决这个问题,但 QMap 似乎不支持这一点。不过,还有另一个技巧:插入一个空向量,然后 swap 地图中带有空向量的完整向量。

最简单且非常惯用的方法是:

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

您会经常在 Qt 和其他代码中看到这种模式,这是最简单的方法,在 C++98 和 C++11 上同样有效:)

这样您就可以处理地图中已有的矢量。矢量本身永远不会被复制。 vector的成员被复制,但是它们是隐式共享的,所以复制实际上是指针复制和原子引用计数增量。