迭代器适配器(一)back_inserter和front_inserter的实现

本文讨论back_inserter和front_inserter的实现。

当我们调用copy函数的时候,要确保目标容器具有足够大的空间,例如:

//将other的所有元素拷贝到以coll.begin()为起始地址的位置
copy(other.begin(), other.end(), coll.begin());

如果之前没有为coll分配好内存,那么会引发越界错误。

如果我们无法提前预分配内存,那么怎么办?我们可以使用如下的代码:

//将other的所有元素拷贝到以coll.begin()为起始地址的位置
copy(other.begin(), other.end(), back_inserter(coll.begin()));

我们用了一个东西叫做back_inserter,它是一种插入迭代器(后面你会看到,它实际是个函数),那么插入迭代器是什么?

我们知道,迭代器用来实现容器操作的一种抽象,有了迭代器,那么我们遍历所有容器,采用的几乎都是同一种方式,换句话说,迭代器帮我们屏蔽了容器操作的细节。

对于元素的插入,不同的容器有不同的操作,例如push_back、insert等,插入迭代器就是帮我们屏蔽插入元素的细节,使得iter看起来总是指向一个“可用的位置”。

back_inserter的使用如下:

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;

template <typename T>
void printElems(const T &t, const string &s = "")
{
    cout << s << " ";
    for(typename T::const_iterator it = t.begin();
        it != t.end();
        ++it)
    {
        cout << *it << " ";
    }
    cout << endl;
}

int main(int argc, char const *argv[])
{
    vector<int> coll;
    back_insert_iterator<vector<int> > iter(coll);
    *iter = 1;
    iter++;
    *iter = 2;
    ++iter;
    *iter = 3;
    printElems(coll);

    back_inserter(coll) = 44;
    back_inserter(coll) = 55;

    printElems(coll);

    copy(coll.begin(), coll.end(), back_inserter(coll));
    printElems(coll);

    return 0;
}

可以看出,插入迭代器的使用很简易,而且不需要我们考虑内存的分配,因为迭代器内部帮我们处理了这些细节。正如前面所说,插入迭代器总是指向一块可用的位置,我们很快即将看到它的细节实现。

需要注意一下几点:

1.插入迭代器本质上是一种适配器,但是它看起来像一个迭代器,行为像一个迭代器,那么他就符合迭代器的定义。

2.插入迭代器的赋值,内部采用了插入元素的做法,可能调用容器的push_back push_front或者insert等。

3.插入迭代器的++操作,只是个幌子,但必不可少。以上面的copy为例,内部肯定调用了iter++,因为copy函数只是把它当做普通迭代器。

4.解引用操作同样也是幌子。

back_inserter和front_inserter实现代码如下

#ifndef ITERATOR_HPP
#define ITERATOR_HPP

template <typename Container>
class BackInsertIterator
{
public:
    typedef typename Container::value_type value_type;

    explicit BackInsertIterator(Container &cont) :cont_(cont) { }

    BackInsertIterator<Container> &operator=(const value_type &val)
    {
        cont_.insert(cont_.end(), val);
        return *this;
    }

    BackInsertIterator<Container> &operator*()
    {
        return *this;
    }

    BackInsertIterator<Container> &operator++()
    {
        return *this;
    }
    //iter++没有实质操作,所以也是返回引用
    BackInsertIterator<Container> &operator++(int)
    {
        return *this;
    }

private:
    Container &cont_;
};

template <typename Container>
BackInsertIterator<Container> backInserter(Container &c)
{
    return BackInsertIterator<Container>(c);
}

//FrontInsertIterator
template <typename Container>
class FrontInsertIterator
{
public:
    typedef typename Container::value_type value_type;

    explicit FrontInsertIterator(Container &cont) :cont_(cont) { }

    FrontInsertIterator<Container> &operator=(const value_type &val)
    {
        cont_.insert(cont_.begin(), val);
        return *this;
    }

    FrontInsertIterator<Container> &operator*()
    {
        return *this;
    }

    FrontInsertIterator<Container> &operator++()
    {
        return *this;
    }
    FrontInsertIterator<Container> &operator++(int)
    {
        return *this;
    }

private:
    Container &cont_;
};

template <typename Container>
FrontInsertIterator<Container> frontInserter(Container &c)
{
    return FrontInsertIterator<Container>(c);
}

 

从上面的源码我们可以看到,二者插入均采用的insert操作。当然,调用push_back和push_front也是可以的

时间: 2024-11-06 15:54:34

迭代器适配器(一)back_inserter和front_inserter的实现的相关文章

C++ Primer 学习笔记_54_STL剖析(九):迭代器适配器{(插入迭代器back_insert_iterator)、IO流迭代器(istream_iterator、ostream_i

回顾 适配器 1.三种类型的适配器: (1)容器适配器:用来扩展7种基本容器,利用基本容器扩展形成了栈.队列和优先级队列 (2)迭代器适配器:(反向迭代器.插入迭代器.IO流迭代器) (3)函数适配器:函数适配器能够将仿函数和另一个仿函数(或某个值.或某个一般函数)结合起来. [1]针对成员函数的函数适配器 [2]针对一般函数的函数适配器 一.迭代器适配器 1.反向迭代器 2.插入迭代器 3.IO流迭代器 其中反向迭代器,利用正向迭代器实现可以参考以前<46_STL剖析(三)>. 二.插入迭代

STL 迭代器适配器(iterator adapter)

iterator adapter graph LR iterator --- reverse_iterator iterator --- Insert_iterator iterator --- iostream_iterator Insert_iterator --- back_insert_iterator Insert_iterator --- front_insert_iterator Insert_iterator --- insert_iterator 插入迭代器:将一般迭代器的赋值

迭代器适配器(二)general inserter的实现

上节我们实现了back_inserter和front_inserter,接下来是更为普通的插入迭代器,它允许用户指定插入位置. 实现代码如下: #ifndef ITERATOR_HPP #define ITERATOR_HPP template <typename Container> class InsertIterator { public: typedef typename Container::value_type value_type; typedef typename Contai

迭代器适配器(二) general inserter的简单实现

general inserter允许用户在指定位置插入. 实现代码如下: 1 #ifndef ITERATOR_H 2 #define ITERATOR_H 3 #include <iterator> 4 5 //BackInsertIterator 6 template <typename Container> 7 class InsertIterator 8 { 9 public: 10 typedef typename Container::value_type value_

SGI-STL简记(十一)-适配器(容器、迭代器、仿函数)

适配器(adapters): 概念上类似于设计模式中的适配,此处STL中的适配器可对组件的组合.灵活运用扮演重要角色. STL中适配器主要有:容器适配器.迭代器适配器.仿函数适配器 容器适配器: queue(先进先出).stack(先进后出).priority_queue(优先队列)适配器,即queue和stack的_Sequence序列模板参数默认类型为deque<T>(双端队列), 当然也可以是其他满足适配器的必要接口的容器也可,故这几个可认为是序列模板容器_Sequence的包装器. 迭

C ++ 插入迭代器

C++ 语言提供了三种插入器,其差别在于插入元素的位置不同. (1)back_inserter,创建一个使用push_back 实现插入的迭代器. (2)front_inserter,创建一个使用push_front实现的插入迭代器. (3)inserter,使用insert实现的插入,此外还带有第二个实参:指向插入起始位置的迭代器. back_inserter 是一种迭代器适配器,它与容器适配器一样,是以一个容器对象作为实参,生成一个适应期实参行为的迭代器.举例说明其用法. 1 vector<

STL适配器的初步理解

c++中的适配器有三种:容器适配器,迭代器适配器,函数适配器.下面一一介绍: 1.容器适配器:因为这些容器都是基于其他标准容器实现的所以叫做容器的适配器,具体的有stack,queue,priority_queue,默认的情况下,stack和queue基于deque而实现的,,priority_queue在vector上实现的,可以根据第二个实参指定容器的类型,但一定要符合标准,queue要求要有push_front操作因此不能建立在vector上面,priority_front要求有随机访问的

【足迹C++primer】33、再探迭代器

再探迭代器 这里有插入迭代器,有流迭代器,反向迭代器,移动迭代器. 插入迭代器 这是一种迭代器适配器,接受一个容器,生成一个迭代器,实现向给定容器添加元素. 插入迭代器有三种类型,差异在于元素插入的位置 back_inserter创建一个使用push_back的迭代器. front_inserter创建一个使用push_front的迭代器. inserter创建一个使用insert的迭代器. void fun1() { list<int> lst={1,2,3,4}; list<int&

C++ Primer 学习笔记_42_STL实践与分析(16)–再谈迭代器【上】

STL实践与分析 --再谈迭代器[上] 引言: 另外三种迭代器类型: 1)插入迭代器:这类迭代器与容器绑定在一起,实现在容器中插入元素的功能. 2)iostream迭代器:这类迭代器可以与输入与输出流绑定在一起,用于迭代遍历所关联的IO流. 3)反向迭代器:这类迭代器实现向后遍历,而不是向前遍历,所有的容器都定义了自己的reverse_iterator类型,由rbegin和rend成员函数返回. 上述迭代器都在iterator头文件中定义. 一.插入迭代器 前面曾经提到的back_inserte