为啥 std::distance() for std:list<int>::iterator 在 last 在 first 之前不返回负数?
Posted
技术标签:
【中文标题】为啥 std::distance() for std:list<int>::iterator 在 last 在 first 之前不返回负数?【英文标题】:Why does std::distance() for std:list<int>::iterator not return a negative number when last is before first?为什么 std::distance() for std:list<int>::iterator 在 last 在 first 之前不返回负数? 【发布时间】:2019-09-27 00:35:18 【问题描述】:std::distance
在std::list
上给我一个圆形距离,而不是相对距离。为什么?
#include <list>
#include <iostream>
#include <iterator>
using namespace std;
int main()
list<int> derp = 1,2,3,4;
auto begin = derp.begin();
auto end = derp.end();
end--;
cout << distance(end, begin) << endl;
cout << distance(begin, end) << endl;
当我运行它时,会发生以下输出:
2
3
我希望得到以下结果:
-3
3
为什么会这样?
【问题讨论】:
您为什么期望3
是std::distance(begin, end)
的结果?我实际上希望4
。
【参考方案1】:
您的代码具有未定义的行为。对于std::distance
如果
InputIt
不是LegacyRandomAccessIterator,如果通过(可能重复地)递增first
无法从first
访问last
,则行为未定义。如果InputIt
是LegacyRandomAccessIterator,则如果无法从first
访问last
并且无法从last
访问first
,则行为未定义。
std::list
的迭代器不是 RandomAccessIterator,它的begin
不能通过增加end
从end
访问。
【讨论】:
好的。是否有一种标准方法来检测 last 是否可以通过递增从 first 到达?我可能只需要实现我自己的。 @CollinBell AFAIK 没有这样的方法;对于所有 stl 容器和原始数组都是如此,它们的end
可以通过递增从begin
到达。 std::distance
也不会执行这样的检测,如果无法访问就离开 UB。
@CollinBell 您可以使用std::iterator_traits
来检查一个迭代器类型是否是随机访问,但是给定两个指向相同序列的任意非随机访问迭代器,无法分辨哪个在前另一个,因为他们没有实现operator<
。您将无法实现自己的。【参考方案2】:
对于不满足 random access iterator 要求的迭代器,std::distance
返回 first
(第一个参数)必须递增到等于 last
(第二个参数)的次数。
您正在使用std::list
,它没有随机访问迭代器。对于distance(end, begin)
,无论你增加多少次end
,它永远不会等于begin
。因此,行为是未定义的,结果取决于您的标准库实现的细节。
【讨论】:
以上是关于为啥 std::distance() for std:list<int>::iterator 在 last 在 first 之前不返回负数?的主要内容,如果未能解决你的问题,请参考以下文章
在std :: list中,std :: distance(it.begin(),std :: prev(it.end())是否等于list.size()? [重复]