std::distance 返回 signed 类型(如 std::ptrdiff_t)而非 size_t,因其需支持负距离(如反向遍历);vector 中为 O(1),list 中为 O(n),因前者迭代器支持减法,后者仅支持增减操作。
std::distance 为什么返回 long 而不是 size_t?
因为
要支持反向遍历和负偏移——比如从
往回走到
,结果得是负数。而
是无符号类型,没法表示负距离。所以它用的是带符号整型,通常是
或
(后者才是标准规定的返回类型)。
常见错误现象:
—— 在 64 位系统上如果
是
,直接赋给
可能截断。
始终用
或直接用
接收返回值
不要假设它是
或
;尤其在做指针算术或容器索引转换时要小心符号问题
随机访问迭代器(如
)下
是 O(1),但对
这类双向迭代器是 O(n)
vector 和 list 调用 std::distance 的性能差异有多大?
差别本质来自迭代器类别:vector 迭代器支持
,list 迭代器只支持 ++/--,
必须靠循环计数。
使用场景举例:想判断两个
是否“相距不到 5 步”,写
立即学习
“
C++免费学习笔记(深入)
”;
、
、原生指针:O(1),底层就是
、
:O(n),必须逐个递增起始迭代器直到等于终点
若需频繁测距,优先考虑用索引(
)或改用支持随机访问的容器
std::distance 在自定义迭代器里怎么正确实现?
如果你写了可随机访问的迭代器(比如封装了 raw pointer),必须重载
,否则
会退化到泛型版本(即循环计数),哪怕你的迭代器逻辑上支持 O(1) 计算。
C知道
CSDN推出的一款AI技术问答工具
下载
错误示范:迭代器类里只实现了
和
,没实现
→
就当它是输入迭代器用。
随机访问迭代器必须提供
返回类型必须和
一致(通常用
)
别忘了在
特化中正确声明
用 std::distance 算两个 vector::iterator 的距离,结果为负正常吗?
完全正常,只要第一个迭代器在第二个“后面”。比如:
—— 结果是负数,约等于
。
容易踩的坑是拿这个值直接当数组下标用:
,这会越界甚至触发未定义行为。因为
是负的,而
不检查符号。
确保左迭代器不晚于右迭代器,或显式处理符号:
更安全的做法:用
配合方向判断,而不是直接参与索引运算
调试时打印
最常被忽略的一点:
对无效迭代器不报错,也不抛异常,它只是按内存布局瞎算——结果看起来像数字,但毫无意义。
std::distanceend()begin()size_tlongstd::ptrdiff_tauto d = std::distance(it1, it2); int x = d;std::ptrdiff_tlong longintstd::iterator_traits::difference_type autointsize_tvector::iteratorstd::distancelistoperator-std::distancelist::iteratorstd::distance(a, b) 看似简洁,实际每次调用都可能遍历最多 5 次节点——不如手动走 5 步并提前退出。vectorstringlast - firstlistforward_listvectoroperator-std::distanceoperator++operator==operator-std::distancedifference_type operator-(const self& other) conststd::iterator_traits::difference_type std::ptrdiff_tstd::iterator_traitsiterator_category = std::random_access_iterator_tagauto it1 = v.end(); auto it2 = v.begin(); auto d = std::distance(it1, it2);-v.size()v[d]dvector::operator[]if (d std::abs(d)std::cout 前先确认两个迭代器所属同一容器且有效——跨容器或悬垂迭代器会导致未定义行为std::distance