当前位置: 首页 > news >正文

为什么栈内存比堆内存速度快?

 博主介绍:程序喵大人

  • 35- 资深C/C++/Rust/Android/iOS客户端开发
  • 10年大厂工作经验
  • 嵌入式/人工智能/自动驾驶/音视频/游戏开发入门级选手
  • 《C++20高级编程》《C++23高级编程》等多本书籍著译者
  • 更多原创精品文章,首发gzh,见文末
  • 👇👇记得订阅专栏,以防走丢👇👇
    😉C++基础系列专栏
    😃C语言基础系列专栏
    🤣C++大佬养成攻略专栏
    🤓C++训练营
    👉🏻个人网站

最主要还是因为栈内存和堆内存的管理方式不同。

内存管理方式不同

栈内存

  • 栈内存是由编译器自动管理的,内存的分配和释放遵循 后进先出(LIFO) 的原则。

  • 栈内存的分配和释放是通过移动栈指针来实现的,这肯定是一个非常快速的操作。

    • 分配:栈指针向下移动,分配内存。

    • 释放:栈指针向上移动,释放内存。

堆内存

  • 堆内存是由程序员手动管理的,内存的分配和释放需要通过动态内存分配器(如 mallocnew)来完成。

  • 堆内存的分配和释放需要维护一个复杂的内存池,可能涉及很多复杂的操作,比如:

    • 查找合适大小的空闲内存块。

    • 分割或合并内存块以优化内存使用。

    • 处理内存碎片问题。

操作系统的介入

栈内存

  • 栈内存的分配和释放完全由程序控制,不需要操作系统的介入。

  • 栈内存的操作是用户态的操作,速度非常快。

堆内存

  • 堆内存的分配和释放可能涉及操作系统的介入(如通过 brkmmap 系统调用扩展堆空间)。

  • 堆内存的操作可能涉及 用户态和内核态 的切换,这会增加额外的开销。

内存碎片问题

栈内存

  • 栈内存的分配和释放是顺序的,不会产生内存碎片问题。

堆内存

  • 堆内存的分配和释放是随机的,可能会导致内存碎片问题。

  • 内存碎片会降低内存分配器的效率,增加分配和释放的时间。

缓存局部性

栈内存

  • 栈内存的分配是连续的,具有良好的缓存局部性

  • CPU 缓存可以高效地预取栈内存中的数据,提高访问速度。

堆内存

  • 堆内存的分配是分散的,缓存局部性较差。

  • CPU 缓存可能无法高效地预取堆内存中的数据,导致访问速度较慢。

线程安全性

栈内存

每个线程都有自己的栈,栈内存的分配和释放是线程私有的,不需要考虑线程同步问题。

堆内存

堆内存是全局共享的,分配和释放可能涉及线程同步问题(如锁机制),增加额外的开销。

代码示例

#include <iostream>
#include <chrono>void stackMemory() {auto start = std::chrono::high_resolution_clock::now();for (int i = 0; i < 1000000; ++i) {int arr[100]; // 栈内存分配}auto end = std::chrono::high_resolution_clock::now();std::cout << "Stack time: "<< std::chrono::duration_cast<std::chrono::microseconds>(end - start).count()<< " microseconds" << std::endl;
}void heapMemory() {auto start = std::chrono::high_resolution_clock::now();for (int i = 0; i < 1000000; ++i) {int* arr = new int[100]; // 堆内存分配delete[] arr; // 堆内存释放}auto end = std::chrono::high_resolution_clock::now();std::cout << "Heap time: "<< std::chrono::duration_cast<std::chrono::microseconds>(end - start).count()<< " microseconds" << std::endl;
}int main() {stackMemory();heapMemory();return 0;
}

输出结果

Stack time: 1267 microseconds
Heap time: 13792 microseconds

从结果可以看出,栈内存的分配和释放速度远远快于堆内存。

总结

栈内存的申请和释放速度快于堆内存,主要原因包括:

  1. 栈内存的管理是自动且顺序的,而堆内存的管理是手动且随机的。

  2. 栈内存的操作不涉及操作系统和线程同步,而堆内存可能涉及系统调用和锁机制。

  3. 栈内存具有良好的缓存局部性,而堆内存的缓存局部性较差。

  4. 栈内存不会产生内存碎片问题,而堆内存可能会产生内存碎片。

    码字不易,欢迎大家点赞关注评论,谢谢!


C++训练营

专为校招、社招3年工作经验的同学打造的1V1 C++训练营,量身定制学习计划、每日代码review,简历优化,面试辅导,已帮助多名学员获得大厂offer!

相关文章:

  • .dat 文件一般可以用什么打开
  • Java 序列化与反序列化
  • 支持私有化部署的电子合同平台——一合通
  • RAG5个常见错误
  • Codeforces Round 1020 (Div. 3)(题解ABCDEF)
  • 如何使用@KafkaListener实现从nacos中动态获取监听的topic
  • 浏览器环境下JS执行机制
  • 解锁大数据新视野:构建强大可观测平台
  • femap许可常见问题及解决方案
  • 数字域残留频偏的补偿原理
  • DeepSeek本地部署手册
  • 7.10 GitHub Sentinel CLI开发实战:Python构建企业级监控工具的5大核心技巧
  • canvas画板!随意画!!
  • C语言标准库函数setlocale用法详解
  • 自定义异常处理(全局异常处理)
  • 用python进行OCR识别
  • 《解锁LLMs from scratch:开启大语言模型的探索之旅》
  • “生成式AI大模型、多模态技术开发与应用”学习
  • 谈谈接口和抽象类有什么区别?
  • 在 WSL 安装 OpenFOAM-12
  • 4月制造业PMI为49%,比上月下降1.5个百分点
  • 深入贯彻中央八项规定精神学习教育中央指导组派驻地方和单位名单公布
  • 【社论】人工智能,年轻的事业
  • 当初没有珍惜巴特勒的热火,被横扫出局后才追悔莫及
  • 商务部:一季度我国服务贸易较快增长,进出口总额同比增8.7%
  • 保利发展去年净利润约50亿元,在手现金1342亿元