具有以下代码:
template <class IIt, class OIt>
OIt copy2(IIt begin, IIt end, OIt dest)
{
while (begin != end)
{
//make gap between element addresses
for (int i = 0; i < 99999999; i++)
{
dest++;
}
*dest++ = *begin++;
}
return dest;
}
int main(int argc, char** argv)
{
vector<int> vec({ 1, 2, 3 });
vector<int> vec2;
copy2(vec.begin(), vec.end(), back_inserter(vec2));
for (int i : vec2)
{
cout << i << endl;
}
}
这需要相当长的时间来编译,但最终会得到正确的输出
1
2
3
问题是(在不知道std::vector
的内部实现的情况下,它是C样式的
数组?还是更复杂的结构?),当那些元素的地址(指针)不是顺序的时候,它如何在for(int i:vec2)
中正确地找到这些元素? (即,因为迭代器/指针移动了99999999
)。
我认为OutputIterator
需要具有该属性,只能对其执行一次访问,一次移位。 但是当你在访问它们之间移动(添加)它不止一次时,那么就会有一个差距,在我的情况下这是相当巨大的。 那么它是如何编译的呢?
你被愚弄了。
std::back_inserter
返回的迭代器具有IT++
作为no-op。 那么你创造的那些“缺口”呢? 是啊,什么都没做。
Std::Vector,是C风格的数组吗?
不完全一样,但是它创建的缓冲区在结构上是相同的。
当这些元素的地址(指针)不连续时?
前提是错误的。 向量元素的存储器地址是连续的。 一个对象紧挨着另一个对象开始。
而且,它们是否是顺序的并不重要。 即使链表中的元素在内存中不是连续的,也可以很好地迭代这些元素。
OutputIterator.。。但是当您在访问它们之间移动(添加)它超过一次时,就会有一个间隙
这个假设是不成立的。
在std::back_insert_iterator
的特殊情况下,文档说明:
std::back_insert_iterator<Container>::operator++
什么都不做。
您的for-loop
for (int i = 0; i < 99999999; i++)
{
dest++;
}
不会像你想的那样。 除了从0
迭代到99999999
之外,它对那里没有影响。
当您查看std::back_insert_iterator
时,它显示
[...]。 递增std::back_insert_iterator
是不允许的。
或者如23.5.2.1.1中所述,它只是返回back_insert_iterator
,而不对其执行任何操作。
constexpr back_insert_iterator& operator++();
constexpr back_insert_iterator operator++(int);
#Returns: *this.
意味着dest++;
不起作用。 这使得你所做的所有假设,完全不成立。 由于从0
迭代到99999999
,程序执行时间很长。
它提出了一个问题:那么为什么存在std::back_insert_iterator
重载呢?
来自cpprefereencestd::back_insert_iterator
:
什么都不做。 提供这些运算符重载是为了满足LegacyOutputIterator的需求。 它们使得可以使用表达式*iter++=value
和*++iter=value
向底层容器输出(插入)一个值。