• Insert Iterators(安插型迭代器)


    前言

          C++标准库中提供了数个预先定义的特殊迭代器,也就是所谓的迭代器配接器(iterator adapter),它不仅起到辅助作用,还能赋予整个迭代器更加强大的能力。就像任何东西其行为像函数,我们就可以认为是函数,这样特殊的函数我们称为仿函数;类似的,任何东西,只要其行为类似迭代器,它就是一个迭代器。因此我们可以撰写一些类别,使其具备迭代器接口,但有着各不相同的行为。这些特殊的迭代器就是我们说的迭代器配接器,STL中主要有三种迭代器配接器:

               1.Insert Iterators (安插型迭代器)

               2.Stream Iterators(流迭代器)

               3.Reverse Iterators(逆向迭代器)

    本文主要探讨安插型迭代器的类别和使用,先看一个例子。

    例子一

    int _tmain(int argc, _TCHAR* argv[])
    {
    	list<int> ilist;
    	vector<int> iVec;//ivec初始未指定大小,默认是0
    
    	for (int i = 0; i < 6; i++)
    	{
    		ilist.push_back(i);
    	}
    
    	//iVec.resize(ilist.size()); 方式一
    	//copy(ilist.begin(), ilist.end(), back_inserter(iVec));//方式二:采用迭代器 back_inserter
    	copy(ilist.begin(), ilist.end(), iVec.begin());//目标空间不足,运行奔溃
    	
    	return 0;
    }
    结论:

                 1、执行copy算法时,必须确保目标空间有足够的大小,但ivec的空间大小为0,将源空间的值会逐一的赋值到目标空间ivec中,由于执行涂写操作(赋值),导致程序执行异常。

                 2、采用方式一、二都能确保足够的目标空间,方式二就是此次讨论的安插型迭代器,Insert Iterators会促使目标空间按需要增长

    Insert迭代器

    Insert迭代器,也称为inserts,用来将“赋值新增”操作行为转换为“安插新值”操作,通过这种迭代器,算法可以执行安插(insert)操作而非覆盖行为至于插入位置是在容器的前面或最后,或者某个特定的位置,须视三种不同的insert Iterator 而定。所有的Insert迭代器都属于Output迭代器类型。

    通常算法会将数值赋值给标的迭代器。例如copy()算法:

    namespace std 
    {
    	template <class InputIterator, class OutputIterator>
    	OutputIterator copy(InputIterator from_begin,	//beginning of source
    						InputIterator from_end,		//end of source
    						OutputIterator to_pos)		//beginning or dest
    	{
    		while (from_begin != from_end)
    		{
    			*to_pos = *from_begin;	//copy value
    			++from_begin;			//increment interator
    			++to_pos;
    		}
    
    		return to_pos;
    	}
    }
    我们需要注意的是:*to_pos = values; Insert 迭代器内部会重载“=”,从而将赋值动作转为安插操作,具体见源码。这里分为两个操作:

    1、operator* 是一个无实际动作的动作(no-op),只是简单的传回*this。因此对insert迭代器而言,*pos 与pos其实是等价。

    2、赋值操作被转换为安插操作。不同的insert迭代器会调用容器内部的push_back(),push_front(),insert()成员函数。

    如上描述,对于一个insert迭代器,我们写为 pos = value或者*pos=value。但从概念上理解,使用“*pos = value”更为正确, 如图表1是insert迭代器所有的操作函数。

    Insert Iterator 分类

    1. Back Inserters(安插于容器最尾端)

    Back Inserters的内部调用push_back(),在容器的尾端插入元素,也只有能提供push_back()的成员函数的容器才能使用back insert迭代器,STL中有vector、deque、list。


    2. Front  Inserters(安插于容器最前端)

     front inserts的内部调用push_front(),在容器的最前端插入元素,在STL 容器中能使用该迭代器的容器有deque、list;


    3.General Inserters(一般性安插器)

    对于这种安插型迭代器,简称inserts,该insers内部调用的成员函数是inserter(),并新值和新位置作为参数,所有的STL容器都提供inserter()成员函数,也是唯一能够作用于关联式容器的迭代器。我们知道对于关联式容器进行插入时,不能指定其位置,它的位置有键值决定,在关联式容器中我们给出的位置信息仅仅是一个提示作用,帮助它从什么地方开始搜寻正确的安插位置。

    这里通过分析back_insert_iterator类为例讨论其功能,Back inserter重载operator=完成后端插入,其他类型的迭代器的插入也是通过重载operator=完成,只是调用的函数不同罢了。back_insert_iterator类源码代码如下:

    template<class _Container>
    class back_insert_iterator: public _Outit
    {	// wrap pushes to back of container as output iterator
    public:
    	typedef _Container container_type;
    	typedef typename _Container::reference reference;
    
    	typedef _Range_checked_iterator_tag _Checked_iterator_category;
    
    	explicit back_insert_iterator(_Container& _Cont)
    		: container(&_Cont)
    		{	// construct with container
    		}
    
    	back_insert_iterator<_Container>& operator=(
    		typename _Container::const_reference _Val)
    		{	
    			// push value into container
    			container->push_back(_Val);
    			return (*this);
    		}
    
    	back_insert_iterator<_Container>& operator*()
    		{	
    			// pretend to return designated value
    			return (*this);
    		}
    
    	back_insert_iterator<_Container>& operator++()
    		{	
    			// pretend to preincrement
    			return (*this);
    		}
    
    	back_insert_iterator<_Container> operator++(int)
    		{	
    			// pretend to postincrement
    			return (*this);
    		}
    protected:
    	_Container *container;	// pointer to container
    };

    例子二

    /****************************************************************
    *函数名称:BackInsert
    *功    能:back insertor功能应用
    *作    者:Jin
    *日    期:2016年6月2日
    ****************************************************************/
    void BackInsert()
    {
    	vector<int> nVector;//creat empty vector
    	for (int i = 1;i <= 3;i++)
    	{
    		nVector.push_back(i * 10);
    	}
    	//creat back_insert iterator
    	back_insert_iterator<vector<int> > iter(nVector);
    
    	*iter = 1;	//push_back(1)
    	iter++;		//假装递增,无实际意义
    
    	iter = 2;	//等同于 *iter = 2;push_back(2)
    	*iter = 3;	//push_back(3)
    
    	//output: 10 20 30 1 2 3 
    	PrintElements(nVector,"vector list:");
    
    	//create back inserter and insert element
    	//convenient way
    	back_inserter(nVector) = 44;
    	back_inserter(nVector) = 54;
    
    	deque<int> nDeque;//creat empty deque
    	copy(nVector.begin(), nVector.end(),back_inserter(nDeque));
    	//Output: 10 20 30 1 2 3 44 54
    	PrintElements(nDeque, "queue list:");
    }

    例子三

    void InsertIterator()
    {
    	list <int> iList;
    	for (int i = 1; i < 10; ++i)
    	{
    		iList.push_back(i);
    	}
    
    	vector<int> iVector;
    	//back_inserter 插入末尾
    	copy(iList.begin(), iList.end(), back_inserter(iVector));
    
    	deque<int> iDeque;
    	//front_inserter 插入首部
    	copy(iList.begin(), iList.end(), front_inserter(iDeque));
    
    	set<int> iSet;
    	//only work for associative collections
    	copy(iList.begin(), iList.end(), inserter(iSet, iSet.begin()));
    
    }
  • 相关阅读:
    hdu 1455 N个短木棒 拼成长度相等的几根长木棒 (DFS)
    hdu 1181 以b开头m结尾的咒语 (DFS)
    hdu 1258 从n个数中找和为t的组合 (DFS)
    hdu 4707 仓鼠 记录深度 (BFS)
    LightOJ 1140 How Many Zeroes? (数位DP)
    HDU 3709 Balanced Number (数位DP)
    HDU 3652 B-number (数位DP)
    HDU 5900 QSC and Master (区间DP)
    HDU 5901 Count primes (模板题)
    CodeForces 712C Memory and De-Evolution (贪心+暴力)
  • 原文地址:https://www.cnblogs.com/jinxiang1224/p/8468424.html
Copyright © 2020-2023  润新知