是否为Container迭代器定义了常规覆盖复制模式?

时间:2012-09-26 18:43:44

标签: c++ c++11 iterator containers

以下代码编译得很好,用v2覆盖v1中的值:

std::vector<int> v1 = {1, 2, 3, 4, 5};
std::vector<int> v2 = {6, 7, 8, 9, 10};

std::copy(v1.begin(), v1.end(), v2.begin());

std::copy的第三个参数是OutputIterator。但是,Container要求指定a.begin(),其中a是Container对象,其返回类型应为iterator,其定义为:

  

符合前向迭代器要求的任何迭代器类别。

转发迭代器要求不包括输出迭代器的要求,上面的例子是未定义的吗?我使用迭代器作为输出迭代器,即使没有明显的保证它将是一个。

我很确定上面的代码是有效的,但是,我的猜测是你可以从容器的细节推断出begin()返回的前向迭代器实际上也会支持输出迭代器的要求。在这种情况下,begin() 何时返回输出迭代器?只有当容器为const或其他情况时?

2 个答案:

答案 0 :(得分:8)

如果输出迭代器是可变的,则前向迭代器可以符合输出迭代器的规范,具体取决于序列的类型。它没有明确说明(与输入迭代器要求的事实不同),但如果我们看一下需求表

Output iterator requirements

我们可以去检查给定的前向迭代器是否符合它们:

  

*r = o
  (§24.2.5/1):如果X是可变迭代器,reference是对T的引用

可变引用是可分配的(除非你有一个不可分配的类型,显然)。

  

++rr++*r++ = o
  (§24.2.5 Table 109)   Forward iterator requirements

表109中的第一行与输出迭代器的要求相同,只是前向迭代器没有备注。第二行比输出迭代器更具限制性,因为它指定必须返回reference

底线,如果你有一个可变的前向迭代器到一系列可复制的类型,你就有一个有效的输出迭代器

(从技术上讲,一个具有operator=(...) const和可变成员的类型序列的常量迭代器也符合条件,但我们希望没有人能做到这样的事情。)

答案 1 :(得分:4)

  

转发迭代器要求不包括输出迭代器的要求

这听起来倒退了。 OutputIterators需要满足更少的标准而不是ForwardIterators。 (前向迭代器应该在递增后可重复使用,即将它们递增两次应产生相同的结果)。

因此,提供确定输出迭代器保持有效,直到算法完成。 IOW:

auto outit = std::begin(v2);
std::advance(outit, v1.size()); // or: std::distance(std::begin(v1), std::end(v2))
// outit should still be valid here

修改评论:

  

§24.2.1

     

进一步满足输出迭代器要求的迭代器称为mutable iterators。非可变迭代器称为constant iterators

现在,让我找到将这一点联系在一起的位,说vector::begin()返回 mutable 随机访问迭代器。

获取信息

  

§24.2.5转发迭代器[forward.iterators]

     

1 类或指针类型X满足前向迭代器的要求,如果

     
      
  • X满足输入迭代器(24.2.3),
  • 的要求   
  • X满足DefaultConstructible要求(17.6.3.1),
  •   
  • 如果X是可变迭代器,则引用是对T的引用;如果X是const迭代器,则引用是对const T的引用,
  •   
  • 表109中的表达式有效并具有指示的语义,
  •   
  • X类型的对象提供多次通过保证,如下所述。
  •