通过索引访问向量迭代器?

Accessing a vector iterator by index?

最近我在我的代码库中看到了这段代码(当然这里已经简化了)

auto toDelete = std::make_shared<std::string>("FooBar");
std::vector<decltype(toDelete)> myVec{toDelete};
auto iter = std::find_if(std::begin(myVec), std::end(myVec), 
   [](const decltype(toDelete) _next)
   {
      return *_next == "FooBar";
   });

if (iter != std::end(myVec))
{
   std::shared_ptr<std::string> deletedString = iter[0];
   std::cout << *deletedString;
   myVec.erase(iter);
}

Online Example

现在,我注意到我们在这里通过索引访问迭代器!

std::shared_ptr<std::string> deletedString = iter[0];

我以前从未见过有人通过索引访问迭代器,所以我只能猜测迭代器被当作指针处理​​,然后我们访问指针指向的第一个元素。那么该代码实际上等同于:

std::shared_ptr<std::string> deletedString = *iter;

还是未定义行为?

来自 cppreference documentation 的 RandomAccessIterator:

Expression: i[n]

Operational semantics: *(i+n)

由于astd::vector的迭代器满足RandomAccessIterator的要求,索引它们相当于加法和解引用,就像一个普通的指针。 iter[0] 等同于 *(iter+0),或 *iter

这是 Standard 合规行为

24.2.7 Random access iterators [random.access.iterators]

1 A class or pointer type X satisfies the requirements of a random access iterator if, in addition to satisfying the requirements for bidirectional iterators, the following expressions are valid as shown in Table 118.

a[n] convertible to reference: *(a + n)

请注意, 要求将特定迭代器实现为指针。任何具有重载 operator[]operator*operator+ 并具有上述语义的迭代器 class 都可以工作。对于std::vector,迭代器类别是随机访问迭代器,它需要才能工作。