C++标准泛型算法库的函数为什么设计成不能改变容器大小?


        相信蔡老师应该是看了Primer之后产生的这样的疑问,但首先注意的是C++泛型算法的操作对象从来就不是容器,更别提为什么不能改变容器的大小。泛型算法,无论是只读的(比如find,accumulate)还是可写的(sort,fill),其输入参数都是迭代器,也就是说泛型算法眼中只有迭代器,它是看不到容器的。泛型算法有什么样的特性取决于给它提供的迭代器有什么能力。迭代器按照能力大小可分为输入/输出迭代器、向前迭代器、双向迭代器、随机访问迭代器。这些迭代器能力由低到高,高能力迭代器能够实现低能力迭代器的所有功能。那为什么不将泛型算法直接作用于容器呢?泛型算法,顾名思义,就是一种高层算法,它将各种容器和它们的操作进行了隔离,通过抽象出迭代器这一概念,实现了对所有容器的统一操作。比如array、deque、string、vector这些容器都提供了最高能力的随机迭代器,所以可以对它们进行统一的sort算法,如果没有迭代器这一中间层,算法一定会与底层容器耦合,这就失去了泛型算法的意义,也就是说必须要为每种容器设计独立的算法。现在可以大致确定,迭代器这一概念的重要性,所以我们可以理解泛型算法不能直接改变容器大小,但是如果容器提供的迭代器的能力足够,是可以间接改变大小的。比如:
remove(beg, end, val);
unique(beg, end);
        这类泛型算法最低要求前向迭代器,而恰好array、deque、string、vector、list、forward_list都提供了这种迭代器,所以这些算法可以间接改变这类容器的大小。为什么back_inserter这样的函数能在不违反“不改变容器大小”的规范上在容器尾添加元素?back_insert_iterator、front_insert_iterator、insert_iterator这类的插入迭代器(其实是一种适配器)是独立于容器的,它们属于std空间,而容器迭代器属于自身的子空间中,所以它们的用法是有区别的(注意它们的声明方式):
vector<int> vec;
back_insert_iterator<vector<int>> it = back_inserter(vec);
vector<int>::iterator it = vec.begin();

        插入迭代器是一种适配器,back_insert_iterator必须作用于支持push_back的容器,front_insert_iterator必须作用于支持push_front的容器,仅仅是对这两个方法的封装。所以最好把它们和普通的容器迭代器区分开来。那为什么要把push_back和push_front进行封装呢?原因有两个,一是用着更方便,二是扩充了迭代器的能力,因为容器的迭代器最高也就是随机访问的能力,但是你不能通过迭代器扩充容器。~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~评论里说是不是可以设计删除迭代器?可以当然是可以,迭代器想怎么设计就怎么设计,比如可以像插入迭代器那样通过封装容器的erase方法来构造删除迭代器,但是有什么意义呢?因为通过普通的迭代器已经可以实现删除操作了。比如之前提到的:
remove(beg, end, val)
unique(beg, end)


声明:
作者:Aloys寒风
链接:https://www.zhihu.com/question/28495347/answer/42180143
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值