STL 容器(如 std::vector, std::list, std::map, std::set 等)的内存分配情况

发布于:2024-12-18 ⋅ 阅读:(106) ⋅ 点赞:(0)

STL 容器(如 std::vector, std::list, std::map, std::set 等)的内存分配情况取决于容器的设计。总体上,容器中的元数据部分位于栈上,而存储的元素通常在堆上动态分配。


STL 容器的内存分配结构

  1. 元数据部分

    • 容器本身是一个对象,存储在栈上或其创建位置的内存区域(如全局区或堆区)。
    • 例如,std::vector 本身是一个对象,管理堆内存中实际存储元素的区域。

    示例

    std::vector<int> vec; // `vec` 是一个栈对象,存储容器元信息。
    
  2. 数据部分(存储的元素)

    • 容器中的元素通常存储在堆上,特别是动态大小的容器(如 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::liststd::deque
  • 元数据部分(如头指针、尾指针)位于栈上。
  • 元素和节点存储在堆上,std::list 中每个节点是一个动态分配的块。
3. std::mapstd::set
  • 元数据部分(如根节点指针)在栈上。
  • 存储元素的节点(通常是红黑树节点)动态分配在堆上。
4. std::array
  • std::array 是一个静态大小的容器,所有数据存储在栈上。
  • 它更类似于 C 风格的数组。

示例

std::array<int, 5> arr; // 所有数据都在栈上

内存分配示例

以下代码展示了栈和堆的分配差异:

#include <iostream>
#include <vector>
#include <array>

int main() {
    // 栈上创建一个 std::array
    std::array<int, 3> arr = {1, 2, 3}; // 元数据和元素都在栈上

    // 栈上创建一个 std::vector
    std::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 容器将动态数据放在堆上,它们能够灵活适应不同的内存需求,同时栈上的元数据部分保证了快速访问和轻量级操作。


网站公告

今日签到

点亮在社区的每一天
去签到