C++ primer 薄片系列之 STL 容器和迭代器

容器的比较

vector:元素保存在连续空间中。可变大小数组,支持快速随机访问,在尾部之外的位置插入或删除可能很慢
list:双向列表,只支持顺序访问。在任何位置插入或删除都很快
forward_list:单项列表,只支持单向顺序访问。在链表任何位置插入或者删除都很快
deque:双端队列,支持快速随机访问,在头尾插入,删除很快
string :元素保存在连续空间中。和vector相似,但专门用于字符。随机访问快。在尾部插入或者删除快
array:固定数组,支持快速随机访问,不支持插入和删除。可以复制
常见操作:
push_back: array 和 forward_list 不支持,其他都支持
push_front:list , forward_list 和deque 支持, 其他不支持
insert: vector, deque, list, string 均支持insert. forward_list 的insert 版本较为特殊。

insert(iter, "Hello")会将hello 插入iter的前面
std::forward_list<int> fls = { 1,2,3 };
auto prev = fls.before_begin();
auto cur = fls.begin();
cur = fls.erase_after(prev); //删除prev指向位置之后的元素,返回一个指向被删除元素之后的迭代器,如不存在,则返回尾后元素
print(fls);//2 3

auto prev2 = fls.insert_after(fls.begin(),10);//在迭代器后的位置插入元素,返回一个指向最后一个插入元素的迭代器,如果函数第一个元素是尾后迭代器,则函数未定义
print(fls);//2 10 3 `

迭代器

STL按照算法要求的迭代器操作分类5个迭代器类别。

—-输入迭代器
只读不写,单遍扫描,只能递增
支持的操作:比较两个迭代器相等或者不等,推进迭代器前置或者后置递增运算,读取元素的解引用运算符(*),箭头运算符(->)。
递增输入迭代器可能导致其它指向流的迭代器失效,导致不能保证输入迭代器的状态可以保存下来并用来访问元素。因此只能用于单遍扫描算法

—-输出迭代器
只写不读,单遍扫描,只能递增
支持的操作:推进迭代器的前置或者后置递增运算。 解引用运算符(*)

—-前向迭代器
可读写,多遍扫描,只能递增

—-双向迭代器
可读写,多遍扫描,可递增递减

—-随机访问迭代器
可读写,多遍扫描,支持全部迭代器运算

适配器

适配器是一种机制,能使某种事物的行为看上去像另外一件事物一样。比如一个容器适配器接受一种已有的容器类型,使其行为看起来像一种不同的类型。stack 接受一个顺序容器(如vector, list 等),并使其操作起来像一个stack,而不再是原来的容器类型。
容器,迭代器,函数都有适配器。

容器适配器

主要有stack,queue,priority_queue等

迭代器适配器

插入迭代器

back_inserter, front_inserter, inserter
三个常见的迭代器适配器。back_inserter 和 front_inserter 接受一个容器作为参数,inserter 包含两个参数,第一个是容器,第二个是指向给定容器的迭代器。
    std::list<int> ls1 = { 1,2,3 };
    std::list<int> ls2 = { 4 };
    std::list<int> ls3 = { 5 };
    std::list<int> ls4 = { 6 };
    copy(ls1.begin(), ls1.end(), std::back_inserter(ls2));
    print(ls2); //4,1,2,3
    copy(ls1.begin(), ls1.end(), std::front_inserter(ls3));
    print(ls3); //3,2,1,5
    copy(ls1.begin(), ls1.end(), std::inserter(ls4, ls4.begin()));
    print(ls4);//1,2,3,6

iostream迭代器

扫描二维码关注公众号,回复: 12721366 查看本文章

标准库4个迭代器类型
ostream_iterator, istream_iterator, ostreambuf_iterator, istreambuf_iterator

    //复杂式
    std::istream_iterator<int> in_ite(std::cin);
    std::istream_iterator<int> eof;
    std::vector<int> test;
    while (in_ite != eof)
    {
        test.push_back(*in_ite++);
    }
    print(test);
    std::cin.clear();
    std::cin.ignore();//清除输入缓冲区
    //std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');//清除缓冲区的当前行

    //简单式
    std::istream_iterator<int> in_ite2(std::cin), eof2;
    std::vector<int> test2(in_ite2, eof2);
    print(test2);

    //结合算法和输入流迭代器
    std::istream_iterator<int> in_it(std::cin);
    std::istream_iterator<int> eof;
    std::cout << std::accumulate(in_it, eof, 0) << std::endl;

    //输出流
    //复杂式
    for (auto e : test)
    {
        *out_it++ = e;
    }
    //简单式
    std::ostream_iterator<int> out_it(std::cout, "=="); //每个元素之间被插入了"=="间隔,每次向out_it赋值, 写操作都会被提交
    copy(test.begin(), test.end(), out_it);

反向迭代器

适配器reverse_interator
除了forward_list, 其他容器都支持反向迭代器
    std::ostream_iterator<char> out_it2(std::cout, "!!");
    std::string line = "FIRST,MIDDLE,LAST";
    reverse_interatorfl = std::find(line.crbegin(), line.crend(), ',');
    copy(fl.base(), line.cend(), out_it2); //L!!A!!S!!T
    // 这里fl 指向LAST和MIDDLE 之间的逗号, 而fl.base()指向的是LAST 的第一个字符L,保证了[line.crbegin, fl)  和 [fl.base(), line.cend())指向的是line 中相同的范围。同样
crbegin()指向最后一个元素,而cend()指向最后一个元素的末尾(不存在的元素), 二者也相差一位, 同样的效果

猜你喜欢

转载自blog.csdn.net/jxhaha/article/details/78405862