您的位置:首页 > 编程语言 > C语言/C++

[C++]关于STL慎重选择删除元素的方法

2016-04-18 11:55 471 查看

慎重选择删除元素的方法

1 如果你想删除一个连续内容容器的特定值

Container<int> c;
c.erase(remove(c.begin(), c.end(), 1963), c.end());


当c是vector, deque, string时,此方法最好。

对于list

c.remove(1963);


对于关联容器

c.erase(1963);


注意,关联容器里是没有remove成员函数的。

2 如果要删除满足判别式返回true的值

bool badValue(int i);
// If c is vector,string or deque, that is the best way.
c.erase(remove_if(c.begin(), c.end(), badValue), c.end());

// If c is list, use this way instead.
c.remove_if(babValue);


对于关联容器,我们希望有一个循环来遍历所有的元素从而寻找满足条件的值。但这里有一个小问题。

AssocContainer<int> c;
...
for (AssocContainer<int>::iteerator i = c.begin(); i != c.end(); i++) {
if (badValue(*i)) {
c.erase(i);  // Tha problem occurs!
}
}


这种做法会导致不确定的行为。因为对于关联容器,每次erase后,指向该元素的指针、迭代器、引用全部失效!所以此时,i已经变得无效了。

为了避免这个问题,我们使用一个小技巧。

AssocContainer<int> c;
...
for (AssocContainer<int>::iteerator i = c.begin(); i != c.end(); ) {
if (badValue(*i)) {
c.erase(i++);  // Tha problem disappears!
} else {
i++;
}
}


此时问题解决了!

因为i++会返回旧值,也就是说它把i的值给erase,然后在erase执行前,i+1了,于是i指向下一个元素,同时给erase提供了要删除元素的指针。

完美!

3 如果我们希望不仅删除元素,而且还有附属操作。

例如给写入log文件。

对于关联容器就很简单了。

ofstream logFile;
AssocContainer<int> c;
...

for (AssocContainer<int>::iteerator i = c.begin(); i != c.end(); ) {
if (badValue(*i)) {
logFile << "Erasing " << *i << "\n";
c.erase(i++);
} else {
i++;
}
}


但是对于vector,string,deque等,就不能再使用remove_if了,还是要使用循环。但问题又出现了。

对于vector,string,deque,每删除一个元素都会使指向这个元素后面的所有迭代器、指针、引用全部实现!

但,erase会返回一个指针指向下一个元素。

于是乎,问题又解决了。

ofstream logFile;
SeqContainer<int> c;
...

for (SeqContainer<int>::iteerator i = c.begin(); i != c.end(); ) {
if (badValue(*i)) {
logFile << "Erasing " << *i << "\n";
i = c.erase(i);  // i points to next element.
} else {
i++;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: