为啥 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::distancestd::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

为什么会这样?

【问题讨论】:

您为什么期望3std::distance(begin, end) 的结果?我实际上希望4 【参考方案1】:

您的代码具有未定义的行为。对于std::distance

如果InputIt 不是LegacyRandomAccessIterator,如果通过(可能重复地)递增first 无法从first 访问last,则行为未定义。如果InputItLegacyRandomAccessIterator,则如果无法从first 访问last 并且无法从last 访问first,则行为未定义。

std::list 的迭代器不是 RandomAccessIterator,它的begin 不能通过增加endend 访问。

【讨论】:

好的。是否有一种标准方法来检测 last 是否可以通过递增从 first 到达?我可能只需要实现我自己的。 @CollinBell AFAIK 没有这样的方法;对于所有 stl 容器和原始数组都是如此,它们的end 可以通过递增从begin 到达。 std::distance 也不会执行这样的检测,如果无法访问就离开 UB。 @CollinBell 您可以使用std::iterator_traits 来检查一个迭代器类型是否是随机访问,但是给定两个指向相同序列的任意非随机访问迭代器,无法分辨哪个在前另一个,因为他们没有实现operator&lt;。您将无法实现自己的。【参考方案2】:

对于不满足 random access iterator 要求的迭代器,std::distance 返回 first(第一个参数)必须递增到等于 last(第二个参数)的次数。

您正在使用std::list,它没有随机访问迭代器。对于distance(end, begin),无论你增加多少次end,它永远不会等于begin。因此,行为是未定义的,结果取决于您的标准库实现的细节。

【讨论】:

以上是关于为啥 std::distance() for std:list<int>::iterator 在 last 在 first 之前不返回负数?的主要内容,如果未能解决你的问题,请参考以下文章

C++ for 循环:条件评估

std::distance 很慢,如何改进? [关闭]

在std :: list中,std :: distance(it.begin(),std :: prev(it.end())是否等于list.size()? [重复]

`std::partition()` 的时间复杂度

为啥我的 foreach 比我的 for 循环快? [复制]

为啥使用 st_intersection 而不是 st_intersects?