Stl::map erase与std::vector erase的行为不同

stl::map erase vs std::vector erase behave differently

本文关键字:erase std map Stl vector      更新时间:2023-10-16
 class CSensor
 {
    public:
    CSensor(int nVal1,char* pVal2,unsigned int nVal3);
    CSensor(const CSensor& refMessage);
    const CSensor& operator=(const CSensor& refMessage);
   ~CSensor(void);
   private:
   int m_nVal1;
   char* m_pVal2;   
   unsigned int m_nVal3;
 };
 // vector erase
 std::vector<CSensor> SensorList;
 CSensor obj1(1,"Test1",10);
 SensorList.push_back(obj1);
 CSensor obj2(2,"Test2",11);
 SensorList.push_back(obj2);
 CSensor obj3(3,"Test3",12);
 SensorList.push_back(obj3);
 SensorList.erase (SensorList.begin()+1);

// map erase
    std::map<int ,CSensor> ListSensor;
CSensor obj11(1,"Test1",10);    
CSensor obj12(2,"Test2",11);
CSensor obj13(3,"Test3",12);
ListSensor.insert(std::pair<int,CSensor>(1,obj11));
ListSensor.insert(std::pair<int,CSensor>(2,obj12));
ListSensor.insert(std::pair<int,CSensor>(3,obj13));
ListSensor.erase(2);

我调试了两种情况。在这两种情况下,我都在删除第二个元素。如果是矢量它将第3个元素复制到第二个位置,然后删除第3个位置。

所以当你输入

   List.erase (List.begin()+1);

调用赋值操作符(CSensor=),然后调用析构函数。

在map的情况下,当我做

   ListSensor.erase(2);

只调用析构函数

我已经通过STL矢量vs映射擦除。它说迭代器,无法解释行为。

我的问题是为什么擦除行为不同的这两个STL容器??

这不是.erase 本身的行为,而是每个容器各自工作方式的结果。

从向量中删除

当你从vector (List是一个真的不适合vector的名字,btw)中删除时,它的内容必须被洗牌以填补空白,因为vector的元素总是连续地存储在内存中。

这通常是通过复制(或移动)元素,然后删除剩余的元素来完成的:

  • 内存中的Vector元素:

    +---+---+---+---+---+---+---+---+---+
    | a | b | c | d | e | f | g | h | i |
    +---+---+---+---+---+---+---+---+---+
    
  • 删除"e":

    +---+---+---+---+---+---+---+---+---+
    | a | b | c | d |   | f | g | h | i |
    +---+---+---+---+---+---+---+---+---+
    
  • 通过复制/移动来填充空白:

                       <--
    +---+---+---+---+---+---+---+---+---+
    | a | b | c | d | f | f | g | h | i |
    +---+---+---+---+---+---+---+---+---+
                           <--
    +---+---+---+---+---+---+---+---+---+
    | a | b | c | d | f | g | g | h | i |
    +---+---+---+---+---+---+---+---+---+
                               <--
    +---+---+---+---+---+---+---+---+---+
    | a | b | c | d | f | g | h | h | i |
    +---+---+---+---+---+---+---+---+---+
                                   <--
    +---+---+---+---+---+---+---+---+---+
    | a | b | c | d | f | g | h | i | i |
    +---+---+---+---+---+---+---+---+---+
    
  • 调整容器大小:

    +---+---+---+---+---+---+---+---+
    | a | b | c | d | f | g | h | i |
    +---+---+---+---+---+---+---+---+
    

从映射中删除

对于map来说不是这样,它的内容不一定连续存储在内存中(实际上,复杂性要求意味着它几乎总是一个充满指向不连续数据的指针的树结构)。

这是使用不同容器的原因之一!

vector必须复制被删除元素后面的元素,以覆盖它留下的"洞"。否则这些元素将不再是连续的。

map将元素保存在树结构中,只需要调整一些指针来重新平衡树。

为vector辩护:复制一对元素可能比单独分配树节点并保持树平衡更便宜。总是有权衡的!