std::distance

来自cppreference.com
< cpp‎ | iterator
 
 
迭代器库
迭代器概念
迭代器原语
算法概念与工具
间接可调用概念
常用算法要求
工具
迭代器适配器
流迭代器
迭代器定制点
迭代器操作
distance
(C++11)
(C++11)
范围访问
(C++11)(C++14)
(C++11)(C++14)
(C++17)(C++20)
(C++14)(C++14)
(C++14)(C++14)
(C++17)
(C++17)
 
定义于头文件 <iterator>
template< class InputIt >

typename std::iterator_traits<InputIt>::difference_type

    distance( InputIt first, InputIt last );
(C++17 起为 constexpr)

返回从 firstlast 的路程。

last 不可从 first 通过(可以重复)自增 first 抵达,则行为未定义。

(C++11 前)

InputIt 不是老式随机访问迭代器 (LegacyRandomAccessIterator) ,则若 last 不可从 first 通过(可以重复)自增 first 抵达,则行为未定义。 若 InputIt老式随机访问迭代器 (LegacyRandomAccessIterator) ,则若 last 不可从 first 抵达且 first 不可从 last 抵达,则行为未定义。

(C++11 起)

参数

first - 指向首元素的迭代器
last - 指向范围尾的迭代器
类型要求
-
InputIt 必须满足老式输入迭代器 (LegacyInputIterator) 的要求。若 InputIt 额外满足老式随机访问迭代器 (LegacyRandomAccessIterator) 的要求则操作更高效

返回值

first 走到 last 所需的自增数。若使用随机访问迭代器且 first 可从 last 抵达,则值可能为负。 (C++11 起)

复杂度

线性。

然而,若 InputIt 额外满足老式随机访问迭代器 (LegacyRandomAccessIterator) 的要求,则复杂度是常数。

可能的实现

参阅 libstdc++libc++ 中的实现。


版本一
// 经由标签派发的实现,移除 constexpr 后可用于 C++98
namespace detail {
 
template<class It>
constexpr // C++17 起要求
typename std::iterator_traits<It>::difference_type 
    do_distance(It first, It last, std::input_iterator_tag)
{
    typename std::iterator_traits<It>::difference_type result = 0;
    while (first != last) {
        ++first;
        ++result;
    }
    return result;
}
 
template<class It>
constexpr // C++17 起要求
typename std::iterator_traits<It>::difference_type 
    do_distance(It first, It last, std::random_access_iterator_tag)
{
    return last - first;
}
 
} // namespace detail
 
template<class It>
constexpr // C++17 起
typename std::iterator_traits<It>::difference_type 
    distance(It first, It last)
{
    return detail::do_distance(first, last,
                               typename std::iterator_traits<It>::iterator_category());
}
版本二
// 经由 constexpr if 的实现,可用于 C++17
template<class It>
constexpr typename std::iterator_traits<It>::difference_type
    distance(It first, It last)
{
    using category = typename std::iterator_traits<It>::iterator_category;
    static_assert(std::is_base_of_v<std::input_iterator_tag, category>);
 
    if constexpr (std::is_base_of_v<std::random_access_iterator_tag, category>)
        return last - first;
    else {
        typename std::iterator_traits<It>::difference_type result = 0;
        while (first != last) {
            ++first;
            ++result;
        }
        return result;
    }
}

示例

#include <iostream>
#include <iterator>
#include <vector>
 
int main() 
{
    std::vector<int> v{ 3, 1, 4 };
    std::cout << "distance(first, last) = "
              << std::distance(v.begin(), v.end()) << '\n'
              << "distance(last, first) = "
              << std::distance(v.end(), v.begin()) << '\n';
}

输出:

distance(first, last) = 3
distance(last, first) = -3

参阅

令迭代器前进给定的距离
(函数模板)