大家知道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());

 

你看,通用算法惹的祸,还是要我们用容器本身调用自己的方法来调整吧。这时候你再去遍历容器,他的数据就对了。这个问题反映了本身设计的一个理念,你会为你想要的美丽和简洁,付出其它代价的。哎,所以编程是一个工程而不是科学么。

posted on 2018-03-09 20:54  ker321  阅读(190)  评论(0)    收藏  举报