减 1 与递减迭代器

Byt*_*ter 5 c++ pointers iterator pointer-arithmetic undefined-behavior

“使用 end()-- 迭代到 std::vector 的最后一个元素”的可接受答案中@barry 指出:

请注意,如果 vector::iterator 只是 T* (这将是有效的),则上面的第一种形式是错误的。无论如何,后两者都有效,因此更可取。

参考他的代码:

std::vector<int>::iterator it = --container.end();
std::vector<int>::iterator it = container.end() - 1;
std::vector<int>::iterator it = std::prev(container.end());
Run Code Online (Sandbox Code Playgroud)

这一观点在评论中存在争议,但没有明确的解决方案。这就是我的问题:第一个和第二个之间的语义差异究竟是什么?对于除 之外的结构上的迭代器,答案会有所不同吗vector

Dre*_*ann 11

对于任何标准库容器,成员函数end()都会返回一个右值。在将其分配给变量之前,它是“临时的”。

递减运算符--不需要在右值迭代器上工作。您将修改一个临时变量,C++ 历来已采取措施避免这种情况。

因此,--container.end() 可以在符合标准的 C++ 编译器上进行编译。但也可能不会。

std::prev(container.end())将适用于每个符合标准的编译器。


回顾:

  • --container.end()可能无法编译。这取决于实施。
  • container.end() - 1仅当容器使用随机访问迭代器时才会编译。
  • std::prev(container.end())总是会编译。

如果编译的话,所有三种形式都会产生相同的结果。