Namespaces
Variants

std:: distance

From cppreference.net
Iterator library
Iterator concepts
Iterator primitives
Algorithm concepts and utilities
Indirect callable concepts
Common algorithm requirements
(C++20)
(C++20)
(C++20)
Utilities
(C++20)
Iterator adaptors
Range access
(C++11) (C++14)
(C++14) (C++14)
(C++11) (C++14)
(C++14) (C++14)
(C++17) (C++20)
(C++17)
(C++17)
定义于头文件 <iterator>
template < class InputIt >

typename std:: iterator_traits < InputIt > :: difference_type

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

返回从 first last 的跳数。

如果 InputIt 不是 LegacyRandomAccessIterator ,当 last 不可从 first 抵达时,其行为是未定义的。

如果 InputIt LegacyRandomAccessIterator ,当 first last 彼此不可达时,其行为是未定义的。

目录

参数

first - 指向首元素的迭代器
last - 指向范围末尾的迭代器
类型要求
-
InputIt 必须满足 LegacyInputIterator 的要求。若 InputIt 额外满足 LegacyRandomAccessIterator 的要求,则操作效率更高。

返回值

first last 所需的递增次数。

若使用随机访问迭代器且 first 可从 last 抵达,则返回值可能为负。

(since C++11)

复杂度

线性。

然而,若 InputIt 额外满足 LegacyRandomAccessIterator 的要求,则复杂度为常数级。

可能的实现

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

通过标签分发实现的C++98版本,已移除 constexpr 修饰符
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());
}
通过 if constexpr 实现的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';
              // 该行为是未定义的(直到LWG940)
    static constexpr auto il = {3, 1, 4};
    // 自C++17起,`distance`可用于常量表达式上下文
    static_assert(std::distance(il.begin(), il.end()) == 3);
    static_assert(std::distance(il.end(), il.begin()) == -3);
}

输出:

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

缺陷报告

下列行为变更缺陷报告被追溯应用于先前发布的 C++ 标准。

缺陷报告 应用于 发布时行为 正确行为
LWG 940 C++98 first 可从 last 到达时,措辞不明确 已明确说明

参见

将迭代器前进给定距离
(函数模板)
返回满足特定条件的元素数量
(函数模板)
返回迭代器与哨位之间的距离,或范围起始与末尾之间的距离
(算法函数对象)