2011-03-06 97 views
2

我想了解STL算法。STL - 复制混合容器

复制的定义是:

template<class InputIterator, class OutputIterator> 
    OutputIterator copy (InputIterator first, InputIterator last, OutputIterator result) 

能有人请解释为什么当载体&双端混合了以下工作,但是当载体和台混合失败。

#include <iostream> 
#include <algorithm> 
#include <vector> 
#include <deque> 
#include <deque> 
#include <set> 
using namespace std; 

int main() { 
    int myints[]={10,20,30,40,50,60,70}; 
    vector<int> myvector; 
    vector<int>::iterator it; 

    set<int> mset(myints,myints+8); 
    set<int>::iterator setItr = mset.begin(); 




    deque<int> deq; 
    deq.resize(10); 
    deque<int>::iterator deqItr = deq.begin(); 
    myvector.resize(7); // allocate space for 7 elements 
    copy (myints, myints+7, myvector.begin()); 

    copy (myvector.begin(), myvector.end(), deqItr); 
    cout << "deque contains:"; 
    for (deque<int>::iterator dit=deq.begin(); dit!=deq.end(); ++dit) 
    cout << " " << *dit; 

    cout << endl; 

    //copy (myvector.begin(), myvector.end(), setItr); 


    return 0; 
} 

据我所知,vector/deque有随机访问迭代器,其中set有双向迭代器。我不明白为什么当只需要输入/输出迭代器时编译失败。

PS:这只是一项实验,以提高我的理解:)

回答

5

关联容器(普通的C++ 03)是特殊的容器,它们的元素始终保持排序,通常实现为红黑树。为了保持顺序不变,集合和映射迭代器为关键对象提供常量引用,因此您不能对其进行修改。

特别是对于std::set<T>,迭代器通常会使std::iterator_traits< std::set<T>::iterator >::referenceconst T&,因此在std::copy操作中隐含的分配将失败。

如果你想要做的是插入的元素为一组,你可以使用迭代从<iterator>头,将在集执行insert操作:

std::copy(v.begin(), v.end(), std::inserter(s, s.end())); // s is the set 
+0

感谢您的解释,由于排序问题,它是有意义的。 – 2011-03-06 19:40:49

5

std::vectorstd::deque有一种方式来预分配的空间。 std::set没有。如果不预先分配空间,尝试取消引用您传递给copy的迭代器会产生未定义的行为。

明显的替代方法是使用插入迭代器代替 - 虽然,不幸的是,你仍然需要 几乎 总是使用不同的代码为一组比双端队列或向量:

std::copy(myvector.begin(), myvector.end(), std::back_inserter(mydeque)); 

std::copy(myvector.begin(), myvector.end(), std::inserter(mySet, mySet.end()); 
+0

你并不真的需要不同的代码,第二种方法对'set'和'deque'(或'vector','list' ...):'std :: copy(src.begin(),src.end(),std: :inserter(dst,dst.end()));'可以与两者一起使用。 – 2011-03-06 19:44:13

+0

我不明白为什么需要预先分配。这是为了避免由于传递没有分配内存的迭代器而导致的错误?例如:如果我要删除调整大小并将其传递给副本,它最终会成为seg故障。即预先分配没有帮助。我错过了什么吗? – 2011-03-06 19:47:19

+0

@David:你说得对 - “需要”是错误的词。 “几乎总是使用”会更准确。 – 2011-03-06 19:54:17

0

它的工作原理为载体,因为你可以预先分配空间。对于其他容器,比如map,你需要一个迭代器适配器来为你做。例如,查看insert_iterator。