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个元素复制到第二个位置,而不是它删除第三个位置 .
所以,当你说
List.erase (List.begin()+1);
它调用赋值运算符(CSensor =)然后调用析构函数 .
如果是 Map 我什么时候
ListSensor.erase(2);
它只调用析构函数 .
我经历了STL vector vs map erase . 它谈论Iterator,无法解释行为 .
我的问题是为什么这两个STL容器的擦除行为不同?
2 回答
这不是
.erase
本身的行为,而是每个相应容器如何工作的结果 .从矢量中删除
当你从向量中删除时(List是一个非常差的向量名称,顺便说一句),它的内容必须随机填充以填补空白,因为向量的元素总是连续存储在内存中 .
这通常通过复制(或移动)元素然后切掉剩余部分来完成:
从 Map 中删除
对于 Map 而言,情况并非如此,其内容不一定在内存中连续存储(事实上,复杂性要求意味着它几乎总是一个填充了指向不连续数据的指针的树结构) .
这是拥有不同容器的一个原因!
向量必须复制缓和元素后面的元素以覆盖它留下的“洞” . 否则元素将不再是连续的 .
Map 将其元素保存在树结构中,只需调整一些指针即可重新 balancer 树 .
对于向量的防御:复制几个元素可能比分别分配树节点和保持树 balancer 更便宜 . 总是有权衡!