C 语言

关注公众号 jb51net

关闭
首页 > 软件编程 > C 语言 > C++ std::distance .size()

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

作者: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() 可读性更佳

📌 ​黄金法则​:

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

您可能感兴趣的文章:
阅读全文