说到“堆”,很多人第一反应是那种乱糟糟的数据堆放。其实在计算机里,堆(Heap)是一种重要的数据结构,不是随便堆东西的地方,但它确实能存不少类型的数据。
基本数据类型都能放
像整数、浮点数、字符这些基础类型,堆都能轻松容纳。比如你在程序中动态分配一个整型变量:
int* p = new int(10);这个 10 就是存在堆上的。再比如创建一个浮点数组:float* arr = new float[100];这一百个浮点数也全在堆里。
对象实例常驻堆区
在面向对象的语言里,像 Java 或 C++,用 new 创建的对象通常都放在堆上。比如你写了个 Person 类,然后执行:
Person* person = new Person("小明", 25);这个 person 对象的所有数据——名字、年龄,连带方法的调用上下文,都会被安排在堆空间里。这也是为什么对象能在函数调用结束后还能继续存在。
字符串也是常见住户
尤其是动态生成的字符串,比如用户输入的名字、从网络下载的一段文本,大多会分配在堆上。像 C++ 中的 std::string,内部缓冲区通常是堆分配的。Python 里的字符串虽然管理更隐蔽,但背后也有堆的身影。
复杂结构照样能装
结构体、链表节点、树的结点,这些自定义的复合类型,只要通过动态内存分配,就归堆管。比如你实现一个二叉树:
struct TreeNode {
int val;
TreeNode* left;
TreeNode* right;
};
TreeNode* root = new TreeNode{5, nullptr, nullptr};这个 root 节点就是堆上的一员。每次插入新节点,也都往堆里塞一份数据。
动态数组和容器背后的支撑
像 vector、ArrayList 这类可变长数组,底层依赖堆来扩容。一开始可能只申请一小块,满了就重新在堆上找更大的地儿,把数据搬过去。这种灵活性全靠堆的支持。
注意生命周期管理
堆上数据不会自动清理,不像栈上变量函数结束就消失。C++ 里得手动 delete,Java 靠垃圾回收。要是忘了处理,就会造成内存泄漏,时间一长程序跑得越来越慢,就像房间堆满旧报纸一样堵得慌。