stl :: map erase vs std :: vector erase表现不同

时间:2011-08-11 08:51:10

标签: c++ stl

 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个元素复制到第2个位置,而不是删除第3个位置。

所以,当你说

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

它调用赋值运算符(CSensor =)然后调用析构函数。

如果是我的地图

   ListSensor.erase(2);

它只调用析构函数。

我经历了STL vector vs map erase。   它谈论Iterator,无法解释这种行为。

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

2 个答案:

答案 0 :(得分:5)

这不是.erase 本身的行为,而是各个容器如何运作的结果。

从矢量中删除

当你从向量中删除时(List是一个真的对于一个向量的不良名称,顺便说一句),它的内容必须随机移动以填充间隙因为向量的元素始终连续存储在内存中。

这通常通过复制(或移动)元素然后切掉剩余部分来完成:

  • 内存中的向量元素:

    +---+---+---+---+---+---+---+---+---+
    | 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 |
    +---+---+---+---+---+---+---+---+
    

从地图中删除

地图不是这种情况,其内容不一定是连续存储在内存中(事实上,复杂性要求意味着它几乎总是一个填充了指向不连续数据的指针的树结构)。

答案 1 :(得分:3)

这是拥有不同容器的一个原因!

向量必须复制缓和元素后面的元素以覆盖它留下的“洞”。否则元素将不再是连续的。

地图将其元素保存在树结构中,只需调整一些指针即可重新平衡树。

向量的防御:复制几个元素可能比分别分配树节点和保持树平衡更便宜。总是有权衡!