C++中std::distance 和 .size()的区别小结

 更新时间:2025年07月10日 09:06:51   作者:Ring__Rain  
在C++中,std::distance和.size()虽然都能获取元素数量,但二者的设计目的、适用场景和性能特性有显著差异,下面就来介绍一下两者的区别,感兴趣的可以了解一下

在 C++ 中,std::distance 和 .size() 虽然都能获取元素数量,但二者的设计目的、适用场景和性能特性有显著差异。以下是关键对比及使用建议:

🔍 ​一、核心区别​

​特性​​**std::distance(first, last)**​​**container.size()**​
​使用范围​任意迭代器范围(包括子范围、非容器序列)仅限完整容器(begin() 到 end())
​时间复杂度​随机访问迭代器:​O(1)​;非随机访问:​O(n)​随机访问容器:​O(1)​;部分容器(如 std::list):​O(n)​​
​实现原理​根据迭代器类型动态选择(减法或遍历)容器内部计数器(或遍历计算)
​灵活性​可计算任意两个迭代器的距离(如子区间)仅返回容器总元素数

💡 示例:计算子范围长度时只能用 distance

std::vector<int> vec{1, 2, 3, 4, 5};
auto start = vec.begin() + 1; // 指向 2
auto end = vec.end() - 1;    // 指向 5
int len = std::distance(start, end); // 3(正确)
int size = vec.size();               // 5(无法获取子范围)

⚡ ​二、性能差异:何时优先用.size()?​​

  1. ​随机访问容器(如 std::vector)​​

    • ✅ ​**.size() 更高效​:直接读取内部计数器,时间复杂度 ​O(1)​**​。
    • ❌ std::distance(begin(), end()) 虽也是 O(1),但多一次函数调用开销。
  2. ​非随机访问容器(如 std::list, std::set)​​

    • ⚠️ ​两者性能可能相同​:
      • std::list::size() 在部分实现中需遍历链表(O(n)),与 std::distance 遍历代价一致。
      • 例如 GCC 的 std::list::size() 可能调用 std::distance 实现。
    • ✅ ​建议用 empty() 替代​:若只需检查容器是否为空,empty() 是 ​O(1)​​ 且更安全。

🎯 ​三、必须用std::distance的场景​

计算子范围长度

auto mid = vec.begin() + 3;
int sub_len = std::distance(vec.begin(), mid); // 3(前3个元素)[7,10](@ref)

处理非容器序列(如数组、自定义迭代器)​

int arr[] = {10, 20, 30};
auto len = std::distance(std::begin(arr), std::end(arr)); // 3[3,9](@ref)

泛型编程中兼容任意迭代器
模板代码需支持各种容器时,distance 可统一处理:

template <typename Iter>
void process(Iter start, Iter end) {
    int n = std::distance(start, end); // 兼容链表、向量等[5,8](@ref)
    // ...
}

​四、总结:选择策略​

​场景​​推荐方法​​原因​
获取完整容器元素总数.size()语义清晰,可能更高效(O(1))
检查容器是否为空.empty()绝对 O(1),避免遍历
计算子范围、数组或泛型迭代器的距离std::distance唯一可行方案,灵活兼容
非随机访问容器(如链表)的完整范围长度​**均可,优先 .size()**​性能相同,但 .size() 可读性更佳

📌 ​黄金法则​:

  • 优先用 .size() 获取容器总大小;
  • 涉及子范围、泛型代码或非容器序列时,必须用 std::distance;
  • 检查是否为空时,​**永远用 .empty() 而非 size() == 0**​。

 到此这篇关于C++中std::distance 和 .size()的区别小结的文章就介绍到这了,更多相关C++ std::distance .size()内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C++实现循环队列和链式队列的示例

    C++实现循环队列和链式队列的示例

    下面小编就为大家分享一篇C++实现循环队列和链式队列的示例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2017-12-12
  • 深入探究C++中的容器适配器与仿函数技术

    深入探究C++中的容器适配器与仿函数技术

    C++中的容器适配器和仿函数是实现数据结构与算法的重要技术,容器适配器可以将一个容器转换为另一个形式,仿函数则可以自定义数据类型的比较、排序、计算等行为,提高程序的灵活性和可重用性
    2023-04-04
  • 解读构造函数的调用规则、深拷贝与浅拷贝

    解读构造函数的调用规则、深拷贝与浅拷贝

    本文主要介绍了C++中的默认构造函数、拷贝构造函数以及深拷贝和浅拷贝的概念,并通过实际代码示例进行了详细讲解
    2024-11-11
  • C++中的函数返回值问题

    C++中的函数返回值问题

    这篇文章主要介绍了C++中的函数返回值问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-09-09
  • C语言课程设计之停车场管理问题

    C语言课程设计之停车场管理问题

    这篇文章主要为大家详细介绍了C语言课程设计之停车场管理问题,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • C++内存泄漏检测和解决方法小结

    C++内存泄漏检测和解决方法小结

    内存泄露在编程中是常见的一种问题,一但程序发生内存泄露问题,将导致程序崩溃无法运行,内存泄漏是指程序在运行过程中,由于疏忽或错误导致已分配的内存空间无法被正确释放,本文给大家就介绍了C++中内存泄漏如何检测和解决,需要的朋友可以参考下
    2025-01-01
  • C++高级数据结构之二叉查找树

    C++高级数据结构之二叉查找树

    这篇文章主要介绍了C++高级数据结构之二叉查找树,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-05-05
  • 详解C++异常处理(try catch throw)完全攻略

    详解C++异常处理(try catch throw)完全攻略

    这篇文章主要介绍了详解C++异常处理(try catch throw)完全攻略,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-03-03
  • C++ vector在多线程操作中出现内存错误问题及解决

    C++ vector在多线程操作中出现内存错误问题及解决

    这篇文章主要介绍了C++ vector在多线程操作中出现内存错误问题及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-08-08
  • c语言判断是否素数程序代码

    c语言判断是否素数程序代码

    这篇文章主要介绍了c语言判断是否素数的方法和问题,大家参考使用吧
    2013-11-11

最新评论