由于速度使用标准矢量作为地图,它是否可靠?

时间:2016-07-03 16:22:11

标签: c++ c++11 vector

对于我的嵌入式项目,我使用的是unordered_map,其中十六进制值为键,uint32_t为值。然而,他们非常代价昂贵,而且一些基准测试显示使用向量反而要快得多。 (在中断期间仅持续50us的10us vs. 1us)

由于密钥仅用于排序值和可读性,因此除了unordered_map之外,我没有看到任何好处,除了易用性。

但是,我想知道做这样的事情是否可靠。在某种意义上,我会丢失数据和/或排序,例如,插入操作将两个向量合并在一起?我的矢量看起来像这样:std::vector<uint32_t>并且凹痕总是不同的

使用向量的另一个缺点是我必须使用所需位置预初始化向量,这限制了此方法的灵活性。

// The PARAM_ values are indeces in HEX
dataMapA.insert(dataMapA.begin() + PARAM_MOTOR_ANGLE, 0);
dataMapA.insert(dataMapA.begin() + PARAM_MOTOR_VELOCITY, 0);
dataMapA.insert(dataMapA.begin() + PARAM_JOINT_ANGLE, 0);
dataMapA.insert(dataMapA.begin() + PARAM_SPRING_ANGLE, 0);

如果我不这样做,我就无法存储任何值。

以下可能是一个解决方案,但在定义为私人/公共成员时似乎不起作用。 Eclipse抛出语法错误。

std::vector<uint32_t> dataMapA(10);

所以我想这个问题可以概括为如何使用向量作为键值查找表,并使其尽可能高效,同时仍保持一定的可读性。

1 个答案:

答案 0 :(得分:1)

问题

// The PARAM_ values are indeces in HEX
dataMapA.insert(dataMapA.begin() + PARAM_MOTOR_ANGLE, 0);
dataMapA.insert(dataMapA.begin() + PARAM_MOTOR_VELOCITY, 0);
dataMapA.insert(dataMapA.begin() + PARAM_JOINT_ANGLE, 0);
dataMapA.insert(dataMapA.begin() + PARAM_SPRING_ANGLE, 0);

这绝对不是如何在给定指数处设定值。它可能适用于简单的情况,但如果您insert()没有严格按升序排列,那么您就会遇到麻烦,因为每次调用insert(blah, n)都会移动n处的所有元素,更大的权利1,并将新元素放在n。因此,在这种情况下,您的价值最终会被“指数”所抵消。在哪里你试图存储它们。

insert()(虽然你可以弯曲它以在某些情况下完成其他方法的工作)实际上是在之前或之前添加新值,包括需要做的任何动作如此。

无论如何,如果你在resize()插入之前没有vector,那就是那个UB。传递的迭代器需要对当前size()有效。

如果其中任何一个出错了...我希望我不会使用此MOTOR进入任何车辆。

解决方案

  

如果我不做以上操作,我就无法存储任何值。

是的,你可以。调用 resize(n) 分配和默认构建有效元素,然后使用 operator[] 访问它们。 是你如何索引到一个连续的容器。把它想象成一个数组。在vector的情况下,。如果要进行临时边界检查,请使用stdlib的operator[]调试版;如果要减慢程序速度,请使用.at(index),直到花费大量精力进行查找和替换。

重要的一点:危险的同名reserve()只保留记忆,即增加capacity();它确实增加向量size(),因此超出[size() - 1]之外的虚拟新索引不能被使用(是UB),直到一个元素由一个构造适当的方法。正如我在下面概述的那样,reserve()非常好......只是没有operator[]

替代

另一种insert()不理想的情况是,您只需要在end()的{​​{1}}处插入值。然后,您应该使用vectoremplace_back(forwarded, constructor, arguments)。这些可以与push_back(thingToCopy)合并,例如如果你知道&#39;我将有50个元素,但需要在循环中计算它们&#39;或者您只想现在进行全面分配以减少以后的重新分配次数。

最后,如果您的reserve()始终具有相同的尺寸......为什么它是vector?只需使用编译时大小的数组。以下是两者的示例:

vector

当然,如果您的大多数数组元素都是// if size is not known at compile time: std::vector<std::uint32_t> dataMapA; // Calculate dataMapSize at runtime, then a.resize(dataMapSize); // if size is known at compile time: std::uint32_t dataMapA[DATAMAPSIZE]; // DATAMAPSIZE must be constexpr // or std::array<std::uint32_t, DATAMAPSIZE>; // if you want its added features, e.g. .at(), copyability // then in either case: dataMapA[PARAM_MOTOR_ANGLE] = 0; dataMapA[PARAM_MOTOR_VELOCITY] = 0; dataMapA[PARAM_JOINT_ANGLE] = 0; dataMapA[PARAM_SPRING_ANGLE] = 0; // and std::array and vector offer .at(n) for bounds-checked indexing ,那么您可以构造0来填充它,然后只更新一些非零的情况。