对于我的嵌入式项目,我使用的是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);
所以我想这个问题可以概括为如何使用向量作为键值查找表,并使其尽可能高效,同时仍保持一定的可读性。
答案 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}}处插入值。然后,您应该使用vector
或emplace_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
来填充它,然后只更新一些非零的情况。