STL 容器(如 std::vector
, std::list
, std::map
, std::set
等)的内存分配情况取决于容器的设计。总体上,容器中的元数据部分位于栈上,而存储的元素通常在堆上动态分配。
STL 容器的内存分配结构
-
元数据部分:
- 容器本身是一个对象,存储在栈上或其创建位置的内存区域(如全局区或堆区)。
- 例如,
std::vector
本身是一个对象,管理堆内存中实际存储元素的区域。
示例:
std::vector<int> vec; // `vec` 是一个栈对象,存储容器元信息。
-
数据部分(存储的元素):
- 容器中的元素通常存储在堆上,特别是动态大小的容器(如
std::vector
,std::list
)。 - 当容器需要存储的元素增加或减少时,底层会动态分配或释放堆内存。
示例:
vec.push_back(10); // `10` 被存储在堆内存中。
- 容器中的元素通常存储在堆上,特别是动态大小的容器(如
具体容器的内存分配情况
以下是常见 STL 容器的内存分配方式:
1. std::vector
std::vector
的元数据(如指向数据的指针、大小信息)存储在栈上。- 实际存储元素的内存是在堆上动态分配的。
示例:
std::vector<int> vec; // 栈上创建元数据
vec.push_back(1); // 元素存储在堆上
2. std::list
和 std::deque
- 元数据部分(如头指针、尾指针)位于栈上。
- 元素和节点存储在堆上,
std::list
中每个节点是一个动态分配的块。
3. std::map
和 std::set
- 元数据部分(如根节点指针)在栈上。
- 存储元素的节点(通常是红黑树节点)动态分配在堆上。
4. std::array
std::array
是一个静态大小的容器,所有数据存储在栈上。- 它更类似于 C 风格的数组。
示例:
std::array<int, 5> arr; // 所有数据都在栈上
内存分配示例
以下代码展示了栈和堆的分配差异:
#include <iostream>
#include <vector>
#include <array>int main() {// 栈上创建一个 std::arraystd::array<int, 3> arr = {1, 2, 3}; // 元数据和元素都在栈上// 栈上创建一个 std::vectorstd::vector<int> vec; // 元数据在栈上,数据指针指向堆内存vec.push_back(10); // 元素存储在堆上std::cout << "Address of array: " << &arr << std::endl;std::cout << "Address of vector: " << &vec << std::endl;std::cout << "Address of vector elements: " << &vec[0] << std::endl;return 0;
}
输出示例:
Address of array: 0x7ffceb4dc8a0 // 栈上的地址
Address of vector: 0x7ffceb4dc8b0 // 栈上的地址
Address of vector elements: 0x558df2a4d020 // 堆上的地址
总结
-
栈上:
- 容器的元数据,如大小、容量、指向实际数据的指针。
- 静态大小的容器(如
std::array
)的所有数据。
-
堆上:
- 容器实际存储的动态数据部分(如
std::vector
,std::list
的元素)。 - 特殊数据结构(如
std::map
的红黑树节点)。
- 容器实际存储的动态数据部分(如
通过设计 STL 容器将动态数据放在堆上,它们能够灵活适应不同的内存需求,同时栈上的元数据部分保证了快速访问和轻量级操作。