C/C++中栈(stack)&堆(heap)详解及其作用介绍

目录
  • 概述
  • 程序运行中的栈和堆
  • 堆和栈的差异
  • 申请方式和回收方式
  • 申请后系统的响应
  • 申请效率比较
  • 申请大小的限制
  • 堆和栈中的存储内容

概述

栈 (stack) 是为执行线程流出的内存空间. 堆 (head) 是为动态分配预留的空间.

程序运行中的栈和堆

我们以一段代码来举例:

#include <iostream>
using namespace std;

int a = 0;  // 全局初始化区
char *pt;  // 全局未初始化

int main() {
    int b; // b在栈区
    char s[] = "abc";  // s在栈区
    char *p1;  // 在栈区
    char *p2 = "123";  // "123"在常量区, p3在栈区
    static int c = 0;  // 全局静态初始化区
    char *p3 = new char(65);  // 在堆区
    char *p4 = new char[10];  // 在堆区

    return 0;
}

  • 栈区: 栈区是分配局部变量的空间, 处于相对较高的地址. 栈地址向下增长
  • 堆区: 用于分配程序媛申请的内存空间, 是向上增长的
  • 静态数据区: 分配静态变量, 全局变量的空间
  • 只读区: 分配常量和程序代码

堆和栈的差异

申请方式和回收方式

栈: 栈上的空间是自动分配回收的. 生存周期只在函数的运行过程中, 运行后就释放.

堆: 程序媛根据需要自己申请的空间, 只要程序媛不释放空间, 就一直可以访问到. 一旦忘记释放会造成内存泄漏.

申请后系统的响应

栈: 只要栈的剩余空间大于所申请空间, 系统将为程序提供内存, 否则将报异常提示栈溢出. 响应速度快.

堆: 系统收到程序的申请时, 会遍历空闲内存地址的链表. 寻找第一个空间大于所申请空间的堆节点. 响应速度慢.

申请效率比较

栈: 由系统自动分配, 速度较快, 程序媛无法控制.

堆: 由 new 分配, 一般速度较慢, 而且容易产生内存碎片, 不过用起来最方便.

申请大小的限制

栈: 在 Windows 下, 栈的大小是 2MB. 如果申请的空间超过栈的剩余空间时, 将提示overflow
(栈溢出).

堆: 堆的大小受限于计算机系统中有效的虚拟内存. 堆获得的空间比较灵活, 也比较大.

堆和栈中的存储内容

栈: 函数调用语句的下一条可执行语句的地址, 函数的各个参数, 函数中的局部变量.

堆: 具体内容由程序媛, 我们安排.

注: 当有指针数据成员时, 必须用深复制, 使其使用堆区的空间.

到此这篇关于C/C++中栈(stack)&堆(heap)详解及其作用介绍的文章就介绍到这了,更多相关C++栈(stack)&堆(heap)内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C++堆排序算法实例详解

    本文实例讲述了C++堆排序算法.分享给大家供大家参考,具体如下: 堆中元素的排列方式分为两种:max-heap或min-heap,前者每个节点的key都大于等于孩子节点的key,后者每个节点的key都小于等于孩子节点的key. 由于堆可以看成一个完全二叉树,可以使用连续空间的array来模拟完全二叉树,简单原始的实现如下: #include<iostream> int heapsize=0;//全局变量记录堆的大小 void heapSort(int array[],int n){ void

  • C++堆和栈的区别与联系讲解

    C++中,内存分为5个区:堆.栈.自由存储区.全局/静态存储区和常量存储区. 栈:是由编译器在需要时自动分配,不需要时自动清除的变量存储区.通常存放局部变量.函数参数等. 堆:是由new分配的内存块,由程序员释放(编译器不管),一般一个new与一个delete对应,一个new[]与一个delete[]对应.如果程序员没有释放掉,        资源将由操作系统在程序结束后自动回收. 自由存储区:是由malloc等分配的内存块,和堆十分相似,用free来释放. 全局/静态存储区:全局变量和静态变量

  • C/C++中抽象类详解及其作用介绍

    目录 概述 抽象类 vs 具体类 案例 抽象类的作用 总结 概述 抽象类 (abstract class), 是一些不用来定义对象, 而只作为基类被继承的类. 由于抽象类常用作基类, 所以通常称为抽象基类 (abstract base class). 定义抽象类的唯一目的, 就是去建立派生类. 我们在抽象类基础上要定义出功能各异的派生类, 再用这些派生类去建立对象. 抽象类 vs 具体类 凡是包含纯虚函数的类都是抽象类. 纯虚函数不用实现, 故不能被调用, 抽象类无法建立对象. 抽象类的作用是作

  • C++堆排序算法的实现方法

    本文实例讲述了C++实现堆排序算法的方法,相信对于大家学习数据结构与算法会起到一定的帮助作用.具体内容如下: 首先,由于堆排序算法说起来比较长,所以在这里单独讲一下.堆排序是一种树形选择排序方法,它的特点是:在排序过程中,将L[n]看成是一棵完全二叉树的顺序存储结构,利用完全二叉树中双亲节点和孩子节点之间的内在关系,在当前无序区中选择关键字最大(或最小)的元素. 一.堆的定义 堆的定义如下:n个关键字序列L[n]成为堆,当且仅当该序列满足: ①L(i) <= L(2i)且L(i) <= L(2

  • C/C++中异常处理详解及其作用介绍

    目录 概述 异常处理 异常处理机制 函数声明指定异常 练习 案例一 案例二 概述 作为一名专业写 Bug, 编程一天改 bug 一周的程序媛. 学会异常处理是非常重要的. 我们不仅要考虑没有错误的理想情况, 更要考虑存在错误时的情况. Debug 可以帮助我们尽快发现错误, 消除错误. 错误类别: 语法错误 运行错误 逻辑错误 异常处理 设计程序时, 事先分析程序运行时可能出现的各种意外情况, 定制出相应的处理方法. 异常处理指对运行时出现的差错以及其他例外情况的处理. 没有异常处理程序时, 运

  • C/C++中数据类型转换详解及其作用介绍

    目录 概述 不同类型数据间的转换 隐式类型转换 强制类型转换 自己声明的类型转换 转换构造函数 类型转换函数 案例 应用 概述 在日常的开发中, 我们经常会用到数据类型转换, 所以我们要对数据类型转换有一定的了解. 不同类型数据间的转换 在 C++ 中, 某些标准类型的数据之间可以自动转换. 隐式类型转换 隐式类型转换: 由 C++ 编译系统自动完成的, 我们无需干预. 例如: int main() { int a = 6; a = a + 3.5; cout << a << en

  • C/C++中命名空间(namespace)详解及其作用介绍

    目录 概述 命名空间 命名空间的作用 自定义命名空间 命名空间成员的方法 案例 概述 命名空间 (namespace) 可以帮助我们区分不同库中相同名称的函数, 类, 变量等. 使用了命名空间即定义了上下文. 命名空间就是定义了一个范围. 命名空间 为了解决 C++ 标准库中的标识符与程序中的全局标识符之间以及不同库中的所有标识符之间的命名冲突. 标准 C++ 库的所有标识符都定义在一个名为 std 的命名空间中. 在程序中用到 C++ 标准库时, 使用 std 作为限定. 我们在写 "Hell

  • C/C++中栈(stack)&堆(heap)详解及其作用介绍

    目录 概述 程序运行中的栈和堆 堆和栈的差异 申请方式和回收方式 申请后系统的响应 申请效率比较 申请大小的限制 堆和栈中的存储内容 概述 栈 (stack) 是为执行线程流出的内存空间. 堆 (head) 是为动态分配预留的空间. 程序运行中的栈和堆 我们以一段代码来举例: #include <iostream> using namespace std; int a = 0; // 全局初始化区 char *pt; // 全局未初始化 int main() { int b; // b在栈区

  • C/C++中文件的随机读写详解及其作用介绍

    目录 概述 随机读写 函数 例子 指针流成员函数 随机访问二进制数据 概述 文件的操作方式分为顺序读写和随机读写. 顺序读写指文件的指针只能从头移到尾巴. 随机读写指文件指针可以随意移动, 根据需要. 随机读写 文件指针: 在磁盘文件操作中有一个文件指针, 用来指明进行读写的位置. 函数 文件流提供了一些有关文件指针的成员函数: 成员函数 作用 gcount() 返回最后一次输入所读入的字节数 tellg() 返回输入文件指针的当前位置 seekg (文件中的位置) 将输入文件中指针移到指定的位

  • C/C++中派生类访问属性详解及其作用介绍

    目录 保护继承 派生类成员的访问属性 总结 保护继承 由 protected 声明的成员称为 "受保护的成员", 或简称 "保护成员". 从用户的角度来看, 保护成员等价于私有成员. 保护成员可以被派生类的成员函数引用. 派生类成员的访问属性 4 种访问属性: 公用的: 类内和类外都可以访问 受保护的: 类内可以访问, 类外不能访问, 下一层的派生类可以访问 私有的: 类内可以访问, 类外不能访问 不可访问的: 类内和类外都不能访问 继承方式 基类中的成员 访问属性

  • C++中浅拷贝与深拷贝的详解及其作用介绍

    目录 概述 对象的赋值 对象的复制 对象复制的用途 建立一个新对象 函数的参数为类对象 函数的返回值为类对象 浅拷贝 深拷贝 概述 浅拷贝 (shallow copy) 只是对指针的拷贝, 拷贝够两个指针指向同一个内存空间. 深拷贝 (deep copy) 不但对指针进行拷贝, 而且对指针指向的内容进行拷贝. 经过深拷贝后的指针是指向两个不同地址的指针. 对象的赋值 同类对象之间可以相互赋值. 对象赋值的一般形式: 对象名1 = 对象名2; 举个栗子: int main() { Time t1(

  • C++中static修饰符的详解及其作用介绍

    目录 概述 静态数据成员 引用静态数据成员 用类名访问数据成员 静态成员函数 综合案例 概述 static (静态) 修饰符是用来控制变量的存储方式和可见性的. 静态局部变量存储在静态区域: static 的性质: 局部特性:作用范围仅限于本函数 静态特性:存储在静态区, 函数调用结束后不孝顺而保留原值. 在下一次调用时, 保留上一次调用结束时的值. 静态数据成员 在我们定义全局变量的时候, 我们会发现一个问题: 我们可以在程序各处自由的修改全局变量的值 (不安全). 静态数据成员的特点: 静态

  • C++中对象与类的详解及其作用介绍

    目录 什么是对象 面向过程 vs 面向对象 面向过程 面向对象 什么是类 类的格式 类的成员函数 函数访问权限 方法一 方法二 方法三 inline 成员函数 什么是对象 任何事物都是一个对象, 也就是传说中的万物皆为对象. 对象的组成: 数据: 描述对象的属性 函数: 描述对象的行为, 根据外界的信息进行相应操作的代码 具有相同的属性和行为的对象抽象为类 (class) 类是对象的抽象 对象则是类的特例 面向过程 vs 面向对象 面向过程 面向过程的设计: 围绕功能, 用一个函数实现一个功能

  • C++中构造函数与析构函数的详解及其作用介绍

    目录 构造函数 默认构造函数 有参构造函数 析构函数 析构函数例子 析构函数执行时机 局部对象 全局对象 构造函数 构造函数 (constructor) 是一种特殊的成员函数. 它会在每次创建类的新对象时执行. 构造函数的名称与类的名称是完全相同的, 并且不会返回任何类型. 构造函数可用于为某些成员变量设置初始值. 格式: Class::Class(); // 构造函数 默认构造函数 如果用户自己没有定义构造函数, C++ 系统会自动生成一个默认构造函数. 这个构造函数体是空的, 没有参数, 不

  • C++中const修饰符的详解及其作用介绍

    目录 概述 常对象 常对象成员 常成员函数 常数据成员 数据成员访问限制 常对象修改的限制 常指针 指向常变量的指针 指向对象的指针 小结 对象的常引用 总结 概述 const 是 constant 的缩写, 是不变的意思. 在 C++ 中是用来修饰内置类型变量, 自定义对象, 成员函数, 返回值, 函数参数. const 可以帮我们避免无意之中的错误操作. 使用 const, 把有关的数据定义为常量 (常变量 / 常对象 / 常函数). const 既可以使数据在一定范围内共享, 又要保证它不

  • C/C++ 中memset() 函数详解及其作用介绍

    memset 函数是内存赋值函数,用来给某一块内存空间进行赋值的: 包含在<string.h>头文件中,可以用它对一片内存空间逐字节进行初始化: 原型为 : void *memset(void *s, int v, size_t n); 这里s可以是数组名,也可以是指向某一内在空间的指针: v为要填充的值: n为要填充的字节数: 例子: struct data { char num[100]; char name[100]; int n; }; struct data a, b[10]; me

  • C/C++中字符串流详解及其作用介绍

    目录 概述 字符串流 理解字符串流 输出字符串对象 输入字符串流对象 输入输出字符串流对象 案例一 案例二 字符数组 vs 文件 总结 概述 文件流类和字符串流类都是 ostream, istream 和 iostream 类的派生类, 因此对它们的操作方法是基本相同的. 字符串流 文件流 字符串流 概念 文件流是以外存文件为输入输出对象的数据流 字符串流也 称为内存流, 以内存中用户定义的字符数组 (字符串) 为输入输出的对象 相关流类 ifstream, ofstream 和 fstream

随机推荐