以下代码编译得很好,用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
或其他情况时?
答案 0 :(得分:8)
如果输出迭代器是可变的,则前向迭代器可以符合输出迭代器的规范,具体取决于序列的类型。它没有明确说明(与输入迭代器要求的事实不同),但如果我们看一下需求表
我们可以去检查给定的前向迭代器是否符合它们:
*r = o
(§24.2.5/1)
:如果X
是可变迭代器,reference
是对T
的引用
可变引用是可分配的(除非你有一个不可分配的类型,显然)。
++r
,r++
,*r++ = o
(§24.2.5 Table 109)
表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类型的对象提供多次通过保证,如下所述。