用来将“赋新值操作”转换为“安插新值”操作,通过这种迭代器,算法可以执行安插(insert)操作而非覆盖(overwrite)操作。所有insert迭代器都属于output迭代器。
- Insert迭代器的功能
通常算法会将数值赋值给标的迭代器,如copy()算法
namespace std
{
template<typename InputIterator, typename OutputIterator>
OutputIterator copy(InputIterator from_pos, InputIterator from_end, OutputIterator to_pos)
{
while (from_pos != from_end)
{
*to_pos = *from_pos;
++from_pos;
++to_pos;
}
return to_pos;
}
}
需要注意的是赋值操作会被转换为安插操作,事实上insert迭代器会调用容器的push_back(),push_front()或insert()成员函数。
- 迭代器的种类
事实上它们各自调用所属容器中不同的成员函数,所以insert迭代器初始化时一定要清楚知道自己所属的容器哪一种。每一种insert迭代器都可以由一个对应的便捷函数加以生成和初始化当然,容器本身必须支持insert迭代器所调用的函数,否则insert迭代器就不可用,因此back inserters只能用在vector,deque,list,string上,front inserters只能用在deque和list上。
声明
template <class Container> class back_insert_iterator;
/* 可知其template需要一个容器型别 */
实现如下
template <class Container>
class back_insert_iterator : public iterator<output_iterator_tag,void,void,void,void>
{
protected:
Container* container;
public:
typedef Container container_type;
explicit back_insert_iterator (Container& x) : container(&x) {} //构造函数,需要带入容器型别为参数
back_insert_iterator<Container>& operator= (typename Container::const_reference value) //赋值时调用容器的push_back()操作
{
container->push_back(value);
return *this;
}
back_insert_iterator<Container>& operator* () //什么也不做,只是返回这个对象
{
return *this;
}
back_insert_iterator<Container>& operator++ () //什么也不做,只是返回这个对象
{
return *this;
}
back_insert_iterator<Container> operator++ (int) //什么也不做,只是返回这个对象
{
return *this;
}
};
back_inserter函数声明
template <class Container>
back_insert_iterator<Container> back_inserter (Container& x);
例子如下
#include <iostream>
#include <iterator>
#include <vector>
#include <algorithm>
using namespace std;
int main(void)
{
vector<int> col;
//create back inserter for col
//inconvenient way
back_insert_iterator<vector<int> > iter(col);
*iter = 1;
iter++; //此句什么也不做,有没有一样,所以不必写
*iter = 2;
*iter = 3;
copy(col.begin(),col.end(),ostream_iterator<int>(cout," ")); // 1 2 3
cout << endl;
//create back inserters and insert elements
//convenient ways
back_inserter(col) = 44;
back_inserter(col) = 55;
copy(col.begin(),col.end(),ostream_iterator<int>(cout," ")); // 1 2 3 44 55
cout << endl;
//reserve enough momory to avoid reallocation
col.reserve(2*col.size()); //一定要在copy之前保证足够大的空间
copy(col.begin(), col.end(), back_inserter(col));
copy(col.begin(),col.end(),ostream_iterator<int>(cout," ")); // 1 2 3 44 55 1 2 3 44 55
return 0;
}
/* 可以看出有两种方式使用安插迭代器: 1. 使用其型别,就是使用其类。如back_insert_iterator<vector<int> > ,并加以初始化 2. 调用函数back_inserter(container);其中函数back_inserter()会产生一个back_insert_iterator迭代器 */
看看copy的源代码加强上面理解
template<class InputIterator, class OutputIterator>
OutputIterator copy (InputIterator first, InputIterator last, OutputIterator result)
{
while (first!=last)
{
*result = *first;
++result; ++first;
}
return result;
}
例子如下
#include <iostream>
#include <iterator>
#include <list>
using namespace std;
template<typename T>
inline void PRINT_ELEMENTS(const T& col, const char* str=" ")
{
typename T::const_iterator pos;
cout << str;
for (pos=col.begin(); pos!=col.end(); ++pos)
cout << *pos << ' ';
cout << endl;
}
int main(void)
{
list<int> col;
//create back inserter for col
//inconvenient way
front_insert_iterator<list<int> > iter(col);
*iter = 1;
iter++;
*iter = 2;
iter++;
*iter = 3;
PRINT_ELEMENTS(col); // 3 2 1
//create back inserters and insert elements
//convenient ways
front_inserter(col) = 44;
front_inserter(col) = 55;
PRINT_ELEMENTS(col); // 55 44 3 2 1
copy(col.begin(), col.end(), front_inserter(col));
PRINT_ELEMENTS(col); // 55 44 3 2 1 55 44 3 2 1
return 0;
}
/* 两种方式使用front 迭代器 1. 使用相应的类实例化对象,front_insert_iterator; 2. 使用函数front_inserter(container); */
General Inserters根据两个参数而初始化:(1)容器(2)待安插位置。迭代器内部以“待安插位置”为参数,调用成员函数insert()。函数inserter()则能更方便的产生General Inserter 并初始化;General Inserter对所有标准容器都适用,因为所有容器都有insert()成员函数,然而对关联式容器(sete和maps)而言,安插位置只是个提示,因为在这两种容器中,元素的真正位置视其实值(键值)而定,安插操作完后,general inserter获得刚刚被安插的那个元素的位置,实际上相当于调用
pos = col.insert(pos,value);
++pos;
为什么要将insert()的传回值赋值给pos呢?为了确保该迭代器的位置始终有效,如果没有这个动作,在deque,vector,string中,该general inserter本身可能会失效。因为每一安插操作可能会使指向容器的所有迭代器失效见下例子
#include <iostream>
#include <iterator>
#include <set>
#include <list>
using namespace std;
template<typename T>
inline void PRINT_ELEMENTS(const T& col, const char* str=" ")
{
typename T::const_iterator pos;
cout << str;
for (pos=col.begin(); pos!=col.end(); ++pos)
cout << *pos << ' ';
cout << endl;
}
int main(void)
{
set<int> col;
//create insert inserter for col
//inconvenient way
insert_iterator<set<int> > iter(col,col.begin());
*iter = 1;
iter++;
*iter = 2;
iter++;
*iter = 3;
PRINT_ELEMENTS(col); // 1 2 3
//create insert inserters and insert elements
//convenient ways
inserter(col,col.end()) = 44;
inserter(col,col.end()) = 55;
PRINT_ELEMENTS(col); // 1 2 3 44 55
list<int> col2;
copy(col.begin(), col.end(), inserter(col2,col2.begin()));
PRINT_ELEMENTS(col); // 1 2 3 44 55
copy(col.begin(), col.end(), inserter(col2,++col2.begin()));
PRINT_ELEMENTS(col2); // 1 1 2 3 44 55 2 3 44 55
return 0;
}
/* 两种方式使用general迭代器 1. 使用类创建一个对象,如insert_iterator<container> 2. 使用函数inserter(container,pos) */
// back inserters
back_insert_iterator<container> iter(container);
*iter = val //向后插
back_inserter(container) = val; //向后插
// front inserters
front_insert_iterator<container> iter(container);
*iter = val;
front_inserter(container) = val;
// insert inserters
insert_iterator<container> iter(container,pos);
*iter = val; //在pos后插入
inserter(container,pos); // 在pos后面插入