STL库中的copy函数
template <class InputIterator, class OutputIterator>
OutputIterator copy (InputIterator first, InputIterator last, OutputIterator result);
常规用法:
int myints[] = {10,20,30,40,50,60,70};
vector<int> myvec(7); //这里需要指定vector的长度
copy(myints,myints+7,myvec.begin());
但是如果我们希望这个赋值是插入复制呢?例如:
原数组1:1,2,3,4,5,6
原数组2:10,20,30,40,50,60
插入复制后的数组:10,20,30,1,2,3,4,5,6,40,50,60
那么使用copy如何实现这样的效果呢?
答案是使用库自带的inserter函数。
vector<int> foo, bar;
for(int i=0;i<=5;i++)
{
foo.push_back(i);
bar.push_back(i*10);
}
auto itor = foo.begin();
advance(itor,3); //如果容器是list,那么需要使用advance
//auto itor = foo.begin(); C++11以后已经支持这样的操作了
copy(bar.begin(),bar.end(),inserter(foo,itor));
这样就实现了插入复制操作。
inserter的定义如下:
template <class Container, class Iterator>
insert_iterator<Container> inserter (Container& x, Iterator it);
可见它返回的仍然是一个迭代器,但是这个迭代器指向的内存不属于原来的容器,而是另外开劈出来的。这样就引入了一个问题。我们先看一下copy操作的源码和inserter的源码:
template <class InputIterator, class OutputIterator>
OutputIterator copy (InputIterator first, InputIterator last, OutputIterator result){
while(first!=last){
*result = *first;
++result;++first;
}
return result;
}
template <class Container>
class insert_iterator{
protected:
Container* container; //底层容器
typename Container::iterator iter;
public:
//...
insert_iterator<Container>&
operator=(const typename Container::value_type value)
{
iter = container->insert(iter,value);
++iter;
return *this;
}
}
copy的操作没什么讲的,主要是inserter的操作。我们先感受下inserter的魅力,首先它的返回值是一个迭代器类型,其次它通过运算符重载,使得copy操作悄无声息地与容器自带的insert操作联系了起来,最终实现插入复制操作。这里的核心是操作符重载。
但是,插入复制操作针对非连续地址空间的容器没什么说的,但是对于连续地址空间的容器,比如vector却并不见得那么友好。原因在于其内部重复调用了insert函数,该函数的内部机理涉及到内存的分配。可以这么理解,每调用一次insert函数,vector容器中insert后面的元素就需要进行一次移动,当插入的元素过多,还需要整体搬迁。因此,从效率上讲,这种方式是比较低下的。
更好的方法是,直接使用vector自带的insert函数就支持插入复制
iterator insert (iterator position, const value_type& val);
/* ------------------------------------------------------*/
void insert (iterator position, size_type n, const value_type& val);
/* ------------------------------------------------------*/
template <class InputIterator>
void insert (iterator position, InputIterator first, InputIterator last);