unordered_map 与map使用说明

目录

背景:

问题分析:

使用APE工具,查看录制的原始门信号是否存在异常

查看报文读取是否存在问题

分析报文读取代码

为什么在Windows系统中,解析后的门信号没有存在跳变情况

是否Windows 和Linux下 unordered_map中数据先后位置不一致

验证在相同输入下,在不同操作系统下,存储到队列中数据是否一致,在相同系统下,队列中数据存储是否一致

结论:

容器介绍:

unordered_map:

map:

性能对比:

100w量级的耗时:

参考资料:



背景:

最近在开发一个从文件中解析CAN信号功能时,在Ubuntu系统中发现门信号的状态存在跳变情况,而在Windows系统中,门信号的状态正常。

问题分析:

  • 使用APE工具,查看录制的原始门信号是否存在异常

有图可知,原始信号正常,而解析的门信号存在跳变。

  • 查看报文读取是否存在问题

通过分析,发现从文件中解析出来的can报文就存在跳变情况。

  • 分析报文读取代码

通过分析,发现在两个虚拟通道组中,存在相同的CAN 报文ID ,虚拟通道组分别为35和113。其中35通道组为CAN1通道为DBC文件中报文数据,而113通道组为CAN2通道,不在DBC文件中。

在进行CAN报文解析时,首先是按照虚拟通道组逐个进行解析,并且按照虚拟通道号为key值进行存储到unordered_map中。

在所有虚拟通道组解析完后,将CAN报文数据存储到以CAN ID为key值的unordered_map中。

当存在相同的CAN ID时,就会存在CAN 数据被覆盖的情况。

因此,是由于存在相同CAN ID,导致解析后报文数据别另一个CAN报文内容覆盖的情况,导致信号存在跳变。

  • 为什么在Windows系统中,解析后的门信号没有存在跳变情况

通过分析,CAN报文从虚拟通道组解析后,存储到unordered_map中,由于unordered_map是无序,因此对于虚拟通道组35和113 是随机存储,先后顺序不固定,因此哪个通道组存储在另一个通道后,最后输出的报文就时该报文。

  • 是否Windows 和Linux下 unordered_map中数据先后位置不一致

通过分析,发现Windows和Linux下,unordered_map中key值存储先后顺序不一致.

在Linux下,查看队列存储顺序:

因此,在Linux系统中,实际输出报文内容为113通道数据。(键值转换关系uint32_t id = (i + 1)*10 + channelNumber; i为虚拟通道号,channelNumber为1)

在Windows下,查看队列顺序:

在Windows下,实际输出报文内容为35通道数据,因此,在Windows下,门信号不存在跳变情况。

  • 验证在相同输入下,在不同操作系统下,存储到队列中数据是否一致,在相同系统下,队列中数据存储是否一致

使用同一段代码进行测试,分别验证以上两个问题:

#include <iostream>
#include <unordered_map>
#include <iostream>

int main()
{
    std::unordered_map<uint32_t, uint32_t> map1;
    std::unordered_map<uint32_t, uint32_t> map2;

    for(uint32_t i = 0; i < 10; i++)
    {
        map1[i] = i;
        map2[i] = i;
    }

    std::cout << "map 1 : " <<  std::endl;
    std::unordered_map<uint32_t, uint32_t>::const_iterator iter = map1.begin();
    while (iter != map1.end()) {
        std::cout << " " << iter->first;
        iter++;
    }
    std::cout << std::endl;

    std::cout << "map 2 : " <<  std::endl;
    iter = map2.begin();
    while (iter != map2.end()) {
        std::cout << " " << iter->first;
        iter++;
    }
    std::cout << std::endl;
}

在Linux系统上输出:

在Windows系统上输出:

因此可得:对于unordered_map队列,相同输入情况下,在同一操作系统下,存储key值顺序是一致的,在不同操作系统下,存储的key值顺序是不一致的。

结论:

  • 由于unordered_map队列是无效的,并且在不同操作系统下,内部存储key值顺序是不确定的。
  • 对于不同通道的CAN ID,需要开辟不同存储空间进行存储,当存在相同CAN ID 时避免出现报文覆盖的情况。

容器介绍:

unordered_map:

  • unordered_map是一个无序容器,它基于哈希表(Hash Table)实现。它使用键的哈希值来存储和访问元素,因此在`unordered_map`中插入和查找元素的时间复杂度通常为O(1),具有常数时间复杂度的特点。然而,由于哈希表的实现方式,`unordered_map`的元素顺序是不确定的。

map:

  • map是一个有序容器,它基于红黑树(Red-Black Tree)实现。它以键值对的形式存储数据,并根据键的排序对元素进行排序。这意味着在`map`中插入和查找元素的时间复杂度为O(log n),其中n是容器中的元素数量。由于有序性质,`map`可以高效地进行范围查询和有序遍历。

对于需要存储为有序队列使用map,对于无顺序要求存储,只用unordered_map。由于unordered_map的无效性,对于同样输入顺序,在不同系统上,在内存中存储的顺序是不同的。

性能对比:

100w量级的耗时:

map insert time: 840.515000 ms
map find time: 764.570000 ms
map erase time: 753.324000 ms
unordered_map insert time: 488.741000 ms
unordered_map find time: 228.738000 ms
unordered_map erase time: 255.590000 ms

参考资料:

C++中的unordered_map用法详解-CSDN博客

安全验证 - 知乎

  • 8
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值