提问者:小点点

std::vector如何访问它们之间存在巨大差距的元素?


具有以下代码:

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需要具有该属性,只能对其执行一次访问,一次移位。 但是当你在访问它们之间移动(添加)它不止一次时,那么就会有一个差距,在我的情况下这是相当巨大的。 那么它是如何编译的呢?


共3个答案

匿名用户

你被愚弄了。

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::operator++重载呢?

来自cpprefereencestd::back_insert_iterator::operator++:

什么都不做。 提供这些运算符重载是为了满足LegacyOutputIterator的需求。 它们使得可以使用表达式*iter++=value*++iter=value向底层容器输出(插入)一个值。