大家知道c++的STL实现了非常漂亮的算法和数据结构(主要是各种集合结构)分离,这种抽象给脑的思考带来了很多负担减轻,简洁漂亮的容器和各种通用算法,事实上,这种抽象的实现并非一点问题也没有,比如:
#include <iterator>
#include <algorithm>
#include <iostream>
#include <string>
#include <istream>
#include <ostream>
#include <list>
using namespace std;
int main()
{
list<int>list1;
for (int i = 1; i <= 10; ++i) {
list1.push_back(i);
}
cout << "before: ";
copy(list1.cbegin(),
list1.cend(),
ostream_iterator<int>(cout, " ")
);
cout << endl;
remove(list1.begin(), list1.end(), 3);
cout << "after: ";
copy(list1.cbegin(),
list1.cend(),
ostream_iterator<int>(cout, " "));
cout << endl;
}
上面这段代码的执行结果是
before: 1 2 3 4 5 6 7 8 9 10
after: 1 2 4 5 6 7 8 9 10 10
卧槽,这是什么鬼。为啥后面还多个10,对这就是用iterator操纵数据的滑稽之处,本质上,为了实现把iterator作为接口,但是迭代器就是个指针呀,通过它获取不了关于容器的地址以外的信息,只能去操作指针指向的数据,或者加加减减啥的,所以这些以迭代器为参数的算法,对容器本身的状态和它的方法是鸡毛都不知道的,自然也不可能靠传递指向数据的指针获得,所以上面的数据是改对了,但是维持的容器的其它状态信息,还是鸡毛没变,那么怎么改变这些信息呢?好吧,这就是手工写代码了。首先谢天谢地,指针也不是盖的,还是能够提供删除后结束指针的。
auto end = remove(list1.begin(), list1.end(), 3);
这样我知道了数据结束的位置,那么我去修改容器里面保存的有效数据的长度吧。
list1.erase(end, list1.end());
你看,通用算法惹的祸,还是要我们用容器本身调用自己的方法来调整吧。这时候你再去遍历容器,他的数据就对了。这个问题反映了本身设计的一个理念,你会为你想要的美丽和简洁,付出其它代价的。哎,所以编程是一个工程而不是科学么