1

我想建立一个设备地图,使地图包含:

QString 'DeviceID' 和 QVector '命令列表'

目前我的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,所以也许某种移动语义可以在这里工作?

编辑 我修改了代码中的注释以显示向量不为空。我还要声明,一旦存储数据,我就不需要更改数据。

4

2 回答 2

4

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

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

我正在使用 c++11,所以也许某种移动语义可以在这里工作?

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

如果QMapemplace类似的功能std::map,那么您甚至可以在不移动的情况下就地构造向量。

不过,我对 Qt 并不熟悉,因此您需要从文档中验证这些详细信息。Qt 是否支持移动语义并没有改变手动内存管理很痛苦的事实。


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


再次编辑

如果添加的向量充满了数据,那么复制确实非常昂贵,除非它保持不变。搬家可以弥补这一点,但QMap似乎不支持这一点。不过,还有另一个技巧:插入一个空向量,然后swap在地图中插入带有空向量的完整向量。

于 2016-02-01T17:13:03.177 回答
1

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

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 上同样适用:)

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

于 2016-02-02T14:18:32.753 回答