std::map 中调用 std::copy 的方法

时间:2021-05-20 05:35:15
 
两个std::map,一个是 A,一个是B,A,B 里面都有元素,怎么把 A 里面的元素都赋值给B 呢,一开始想到

std::copy(A.begin(),A.end(),std::back_inserter(B));

编译失败,后面通过查看 c++ 标准库的原始代码,发现 back_inserter 里面构造的对象

  // TEMPLATE FUNCTION back_inserter
template<class _Container> inline
 back_insert_iterator<_Container> back_inserter(_Container& _Cont)
 { // return a back_insert_iterator
 return (std::back_insert_iterator<_Container>(_Cont));
 }

 

std::back_insert_iterator 里面的 operator=() 是这么写的

back_insert_iterator<_Container>& operator=(
  typename _Container::const_reference _Val)
  { // push value into container
  container->push_back(_Val);
  return (*this);
  }

这样就要求 传入的容器必须有 push_back() 方法,但是 std::map 没有提供这类方法,杯具了。模仿 标准库的实现,改写了一下方法,实现了 std::copy 对 std::map 的使用。

 

// TEMPLATE CLASS back_insert_iterator
template<class _Container>
class back_insert_iterator_map
 : public _Outit
{ // wrap pushes to back of container as output iterator
public:
 typedef _Container container_type;
 typedef typename _Container::reference reference;

 explicit back_insert_iterator_map(_Container& _Cont)
  : container(&_Cont)
 { // construct with container
 }

 back_insert_iterator_map<_Container>& operator=(
  typename _Container::const_reference _Val)
 { // push value into container
  container->insert(_Val);
  return (*this);
 }

 back_insert_iterator_map<_Container>& operator*()
 { // pretend to return designated value
  return (*this);
 }

 back_insert_iterator_map<_Container>& operator++()
 { // pretend to preincrement
  return (*this);
 }

 back_insert_iterator_map<_Container> operator++(int)
 { // pretend to postincrement
  return (*this);
 }

protected:
 _Container *container; // pointer to container
};

// TEMPLATE FUNCTION back_inserter
template<class _Container> inline
back_insert_iterator_map<_Container> map_back_inserter(_Container& _Cont)
{ // return a back_insert_iterator
 return (back_insert_iterator_map<_Container>(_Cont));
}

//去处 multimap 里面重复数据的方法
int main(int argc,char *argv[])
{

 std::map<std::string,std::string> iodat;
 iodat["1"] = "1";
 iodat["2"] = "2";
 std::map<std::string,std::string> m_version_map;
 m_version_map.insert(std::make_pair("1","3"));
 m_version_map.insert(std::make_pair("3","3"));
 std::copy(iodat.begin(),iodat.end(),map_back_inserter(m_version_map));

这句编译不过
// std::copy(iodat.begin(),iodat.end(),std::back_inserter(m_version_map));

//进过高人指导 ,下面这句实际也能达到效果,采用了 std::inseter 的迭代器

//std::copy(iodat.begin(),iodat.end(),std::inserter(m_version_map,m_version_map.begin()));

//进过高人指导 ,下面这句实际也能达到效果,采用了 map 的insert 方法

//iodat.insert(m_version_map.begin(),m_version_map.end());

 std::map<std::string,std::string>::const_iterator it;
 for(it = m_version_map.begin();it != m_version_map.end();++it)
 {
  std::cout<<it->first<<":"<<it->second<<endl;
 }

system("pause");

}

 

这样,就实现了调用 std::copy 的时候,也同样适用于 std::map。如果只是交换两个 map 的数据,可以采用 swap 方法。

当然,直接采用循环对两个map 里面的值遍历,一个一个赋值也是可以的。

 

同样的代码,
在 windows 采用 vs2003 编译,耗费时间:
std::copy+std::inserter 在 linux 采用 gcc3.3 编译,耗费时间:
std::copy+std::inserter < std::map.insert < for(iterator..)实现
在 windows 采用 vs2005 编译,耗费时间:
std::copy+std::inserter 略等于 std::map.insert < for(iterator..)实现
在 linux 采用 gcc4.1 编译,耗费时间:
std::map.insert < std::copy+std::inserter < for(iterator..)实现

STL 的实现差异还有有点大