std::distance
来自 cppreference.com
定义在头文件 <iterator> 中 |
||
template< class InputIt > typename std::iterator_traits<InputIt>::difference_type |
(自 C++17 起为 constexpr) | |
返回从 first 到 last 的跃点数。
如果 InputIt
不是 LegacyRandomAccessIterator,如果 last 不能从 first 访问到,则行为未定义。
如果 InputIt
是 LegacyRandomAccessIterator,如果 first 和 last 彼此之间都无法访问,则行为未定义。
内容 |
[编辑] 参数
first | - | 指向第一个元素的迭代器 |
last | - | 指向范围末尾的迭代器 |
类型要求 | ||
-InputIt 必须满足 LegacyInputIterator 的要求。如果 InputIt 另外满足 LegacyRandomAccessIterator 的要求,则操作效率更高。 |
[编辑] 返回值
从 first 到 last 所需的增量次数。
如果使用随机访问迭代器并且 first 可以从 last 访问到,则该值可能为负。 |
(自 C++11 起) |
[编辑] 复杂度
线性。
但是,如果 InputIt
另外满足 LegacyRandomAccessIterator 的要求,则复杂度为常数。
[编辑] 可能的实现
通过标签分派进行 C++98 实现,已删除 constexpr |
---|
namespace detail { template<class It> constexpr // required since 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 // required since 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 // since 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'; // the behavior is undefined (until LWG940) static constexpr auto il = {3, 1, 4}; // Since C++17 `distance` can be used in constexpr context. 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++ 标准。
DR | 应用于 | 发布的行为 | 正确行为 |
---|---|---|---|
LWG 940 | C++98 | 措辞对 first 可以从 last 访问到的情况不清楚 | 已阐明 |
[编辑] 另请参见
将迭代器提前给定距离 (函数模板) | |
返回满足特定条件的元素数量 (函数模板) | |
(C++20) |
返回迭代器和哨兵之间的距离,或范围的开头和结尾之间的距离 (niebloid) |