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

C++ 中的栈(Stack)数据结构与堆的区别与内存布局(Stack vs Heap)

一、栈的基本概念

1. 定义

栈(Stack) 是一种 后进先出(LIFO, Last-In-First-Out) 的线性数据结构。

就像一摞盘子,后放的盘子在最上面,最先被取出。


二、C++ 中的栈实现方式

C++ 中主要有两种方式实现栈:

1. STL 容器适配器 std::stack

#include <stack>
std::stack<int> s;

这是标准库中最常用的实现。

2. 自定义数组或链表实现

可以自己用 vectorlinked list 实现栈逻辑,常见于算法题或底层系统开发。


三、STL std::stack 概述

1. 定义

std::stack 是一个容器适配器 (container adapter),它在内部使用其他容器(如 deque, vector, list)来存储元素。

2. 默认实现

template <class T, class Container = std::deque<T>>
class stack;

即默认底层容器是 std::deque<T>

3. 特性

  • 后进先出(LIFO)
  • 不支持随机访问
  • 只暴露 栈顶操作接口

四、常用成员函数详解

成员函数功能示例
push()入栈s.push(10);
pop()出栈(删除栈顶元素)s.pop();
top()访问栈顶元素int x = s.top();
empty()判断是否为空if (s.empty())
size()返回元素个数s.size();
emplace()原地构造并入栈s.emplace(3, 4);
swap()交换两个栈的内容s1.swap(s2);

五、示例代码

#include <iostream>
#include <stack>
using namespace std;int main() {stack<int> s;// 入栈s.push(10);s.push(20);s.push(30);cout << "Stack top: " << s.top() << endl; // 输出 30// 出栈s.pop();cout << "After pop, top: " << s.top() << endl; // 输出 20cout << "Stack size: " << s.size() << endl;// 清空while (!s.empty()) {cout << "Popped: " << s.top() << endl;s.pop();}
}

输出:

Stack top: 30
After pop, top: 20
Stack size: 2
Popped: 20
Popped: 10

六、底层原理分析

1. 适配器模式

std::stack 并不是一个独立的数据结构,而是对底层容器的封装:

template<class T, class Container = deque<T>>
class stack {
protected:Container c;
public:bool empty() const { return c.empty(); }size_t size() const { return c.size(); }T& top() { return c.back(); }void push(const T& value) { c.push_back(value); }void pop() { c.pop_back(); }
};

2. 底层容器类型选择

容器类型优点缺点
deque双端操作高效(默认)占用稍多内存
vector连续内存、快速访问出栈扩容代价较高
list插入删除快内存碎片多、访问慢

七、内存与性能分析

操作时间复杂度说明
pushO(1)*平均常数时间(vector 可能扩容)
popO(1)删除尾部元素
topO(1)直接访问尾部
empty / sizeO(1)成员变量直接返回

八、应用场景

  1. 表达式求值

    • 中缀转后缀、逆波兰表达式计算
  2. 括号匹配

    • 判断括号是否成对出现
  3. 函数调用栈

    • 系统内部维护函数调用与返回
  4. 回溯算法

    • DFS 深度优先搜索
  5. 撤销(Undo)/恢复(Redo)操作


九、自定义栈实现

使用数组实现:

#include <iostream>
using namespace std;template<typename T, size_t N>
class Stack {T data[N];int topIndex = -1;public:void push(const T& value) {if (topIndex >= N - 1) throw overflow_error("Stack overflow");data[++topIndex] = value;}void pop() {if (topIndex < 0) throw underflow_error("Stack underflow");--topIndex;}T top() const {if (topIndex < 0) throw underflow_error("Empty stack");return data[topIndex];}bool empty() const { return topIndex < 0; }size_t size() const { return topIndex + 1; }
};

十、系统层面理解:调用栈(Call Stack)

除了 STL 数据结构,还是系统内存的一部分。

类型区域功能
栈区 (Stack)由编译器自动分配存储局部变量、函数参数、返回地址
堆区 (Heap)由程序员手动分配存储动态对象(new / malloc)

函数调用时,系统自动使用**调用栈(call stack)**来保存返回地址和局部变量。


十一、堆栈的区别与内存布局(Stack vs Heap)


1、基本概念

名称中文作用分配方式
Stack管理函数调用、局部变量、返回地址等由系统自动分配 / 释放
Heap动态内存存储,由程序员控制由程序员手动分配 / 释放(new/deletemalloc/free

2、从内存布局看区别

以典型的 C/C++ 程序在 Linux 内存布局为例(自低地址到高地址):

+---------------------------+  高地址
|      栈 Stack             |  函数调用栈、局部变量
|      ↓(向下增长)       |
+---------------------------+
|      堆 Heap              |  new / malloc 动态分配(向上增长)
+---------------------------+
|      BSS 段               |  未初始化的全局/静态变量
+---------------------------+
|      数据段 Data          |  已初始化的全局/静态变量
+---------------------------+
|      代码段 Text          |  程序指令、常量
+---------------------------+低地址

特点:

  • 栈向下增长(地址递减)
  • 堆向上增长(地址递增)
  • 二者中间的空间为系统保留的内存或动态共享库区

3、分配与释放机制

比较项栈 Stack堆 Heap
分配方式编译器自动分配程序员手动分配
释放方式离开作用域自动释放需要显式释放(delete/free
分配时间编译期或运行时由编译器管理运行时动态分配
分配效率快(简单移动栈顶指针)慢(涉及操作系统堆管理)
内存碎片不会产生碎片易产生碎片
空间大小一般较小(几 MB)受系统总内存限制(可达 GB)
异常风险栈溢出(Stack Overflow)内存泄漏(Memory Leak)
典型使用局部变量、函数参数动态数组、对象、容器(如 vector)

4、实例分析

栈分配示例:

void func() {int a = 10;   // 分配在栈上double b = 3.14;
}

函数调用时,编译器为 ab 分配栈空间;
函数返回时,这部分内存自动释放。


堆分配示例:

void func() {int* p = new int(10);   // 分配在堆上delete p;               // 手动释放
}
  • new 调用堆管理器(malloc 系统调用)分配空间
  • delete 调用堆释放函数(free)
  • 如果忘记 delete,就会造成 内存泄漏

5、内存使用示意图

#include <iostream>
using namespace std;int g = 0; // 全局变量 → 数据段int main() {int a = 1;                 // 栈变量int* p = new int(2);       // 堆变量static int s = 3;          // 静态变量 → 数据段cout << "stack a: " << &a << endl;cout << "heap  p: " << p << endl;cout << "static s: " << &s << endl;cout << "global g: " << &g << endl;delete p;
}

输出示例(地址大致关系):

stack a: 0x7ffeeff8
heap  p: 0x600010
static s: 0x60104c
global g: 0x601040

可见:

  • 栈区地址较高
  • 堆区地址较低
  • 全局/静态变量在固定的 Data 段
  • 程序代码在 Text 段中

6、性能与风险比较

特性栈 Stack堆 Heap
性能快,连续内存,一次性分配慢,需查找空闲块、更新堆结构
安全性自动释放,易管理容易泄漏、悬垂指针
可变性空间有限可动态扩展
典型错误Stack OverflowMemory Leak / Use-after-free

7、C++ 中的内存管理建议

  1. 优先使用栈对象

    • 自动管理生命周期,不会泄漏。

    • 如:

      std::string s = "hello"; // 栈上管理,内部堆分配自动释放
      
  2. 动态分配时使用智能指针

    • 避免手动 delete
    #include <memory>
    auto p = std::make_shared<int>(42);
    
  3. 不要返回局部变量地址

    int* foo() {int x = 10;return &x;  //  栈变量函数返回后已销毁
    }
    
  4. 避免频繁分配/释放堆内存

    • 建议使用内存池(memory pool)或对象池优化。

8、栈溢出与堆溢出

栈溢出 (Stack Overflow)

原因:函数递归过深或局部数组太大。

void recurse() { recurse(); } // 无限递归 → Stack Overflow

堆溢出 (Heap Overflow)

原因:动态内存越界写入。

int* p = new int[2];
p[5] = 10; // 越界写入 → Heap Corruption

9、程序运行生命周期内存演化图

程序加载时:┌──────────────────────┐│ 代码段(text)       │  ← 程序指令│ 数据段(data + bss) │  ← 全局/静态变量│ 堆(heap)           │  ← new/malloc 动态分配│ ...(空闲空间)...   ││ 栈(stack)          │  ← 函数调用栈帧└──────────────────────┘
  • 程序执行时,栈不断增长/收缩;
  • 堆在运行中动态申请/释放;
  • 数据段和代码段在整个程序生命周期中固定存在。

10、总结对比表

特征栈 (Stack)堆 (Heap)
分配方式系统自动程序员控制
生命周期函数结束自动释放必须手动释放
地址增长方向向下(高→低)向上(低→高)
管理开销
空间大小较小(默认几 MB)较大(受内存限制)
容易出错类型栈溢出内存泄漏、野指针
推荐用法局部变量、临时对象大对象、动态容器、跨函数数据

“栈快且短,堆大但慢;栈自动管,堆需自担。”

http://www.dtcms.com/a/602917.html

相关文章:

  • 设计好网站苏州网站制作电话
  • 建材做网销哪个网站好怎么做企业网站
  • JAVA后端动态代理复习
  • 网站菜单怎么做品牌推广策划
  • thinkphp 网站管理科技网站哪个好
  • C语言编译软件使用教程 | 完整的C语言编译工具介绍与使用技巧
  • [AI tradingOS] AI自动交易器 | 绩效追踪与日志
  • PcVue X 工控——工厂数字化转型与落地巡回研讨会圆满举行
  • 成都哪家做网站比较好旅游网络营销的特点有
  • 青岛社保网站官网登录上海公共招聘平台
  • 计网期末复习--选择题
  • 深入理解 Linux(7) 命令与动态库:从文件操作到程序链接的实践指南
  • 做海外购网站免费的设计网站有哪些
  • 做网站内嵌地图福州建设工程协会网站查询
  • 易语言程序反编译 | 了解易语言反编译的技术与应用
  • 用网站源码怎么做网站腾讯云网站模板
  • 做芯片代理哪个网站推广产品研发
  • 在 MySQL 中使用 `REPLACE` 函数
  • 网站建设陕西wordpress is search
  • 怎么在微信做企业网站东莞建筑设计院排名
  • 仓颉三方库开发实战:技术博客_source_map_js实现详解
  • 建站设计做英文网站用目录还是子域名
  • 网站建设谈客户说什么龙岩兼职招聘最新发布
  • 上海网站建设服务多少钱广西 网站建设
  • 铜仁市城乡住房与建设局网站陕西省两学一做网站
  • 网站商城建设公司网站开发实用技术 代码
  • 外贸网站seo推广教程游戏租号网站开发
  • AI推广公司如何借助人工智能技术提升企业品牌影响力与精准流量
  • Trae,Cursor,Lingma的区别
  • 网站加ico苏州集团网站设计公司