详解C++的静态内存分配与动态内存分配

 更新时间:2023年06月28日 09:49:45   作者:Loup&卡普  
内存分配 (Memory Allocation) 是指为计算机程序或服务分配物理内存空间或虚拟内存空间的一个过程,本文主要介绍了C++的静态内存分配与动态内存分配,感兴趣的同学可以参考阅读

I - 内存分配概述

1.1 - 定义概述

内存分配 (Memory Allocation) 是指为计算机程序或服务分配物理内存空间或虚拟内存空间的一个过程。通常在程序执行前或执行时完成内存分配。

1.2 - 分类概述

存在两种类型的内存分配:

  • 编译时内存分配或静态内存分配 (Compile-time or Static Memory Allocation)
  • 运行时内存分配或动态内存分配 (Run-time or Dynamic Memory Allocation)

静态内存分配

静态内存分配是由编译器为声明的变量分配内存。内存的地址可以通过地址操作符找到,并且可以赋值给指针变量。该内存是在编译时分配的。

动态内存分配 :

在程序执行时 (execution) 或 运行时 (run-time) 进行的内存分配被称为动态内存分配。库函数例如 calloc() 和 malloc() 或者操作符 new 均支持分配动态内存。动态分配的内存空间,通过这些函数或操作符的返回值分配,赋值给指针变量。

1.3 - 区别概述

序号静态内存分配动态内存分配
1在静态内存分配中,变量被永久地分配内存,直到程序执行结束/函数调用结束在动态内存分配中,只有当你的程序单元被激活时才会为变量分配内存
2静态内存分配在程序执行前完成动态内存分配在程序执行过程中完成
3使用栈来管理静态分配的内存使用堆来管理动态分配的内存
4较不高效 (less efficient)较高效
5在静态内存分配中,不存在内存的重用在动态内存分配中,存在内存的重用,而且在不需要时可以内存可以被释放
6在静态内存分配中,一旦内存被分配,内存大小就不能再改变在动态内存分配中,分配了内存后,内存的大小可以改变
7在静态内存分配方案中,我们不能重新使用未使用的内存动态内存分配中,允许重复使用内存。用户可以在需要时分配更多的内存。同时,用户也可以在需要时释放内存。
8在这种内存分配方案中,执行速度比动态内存分配要快在这种内存分配方案中,执行速度要比静态内存分配慢
9编译时内存分配运行时内存分配
10静态分配的内存从程序开始保持到程序结束动态分配的内存可以在任意时刻释放
11静态的内存分配常常用于数组等动态的内存分配常常用于链表等数据结构

II - 静态内存分配

内存必须被分配给我们所创建的变量,这样实际的变量才能存在。现在有一个问题,即我们认为它是如何运行的,以及它实际上是如何运行的?

计算机如何创建一个变量?

当我们思考如何创造某样东西时,我们会想到“从零开始”着手干,而当计算机创建一个变量 ‘X’ 时,实际上情况并不是这样;对于计算机而言,更像是一种分配,计算机只是从许多预先存在的内存单元中分配一个内存单元给 X。

那么什么是静态内存分配?当我们声明变量时,我们实际上是在准备所有会被使用的变量,这样编译器就知道被使用的变量实际上是用户想要的程序的重要部分,而不是到处漂浮的流氓符号。因此,当我们声明变量时,编译器实际做的是将这些变量分配到它们的房间(一个内存单元)。现在,可以看出,这是在程序执行前完成的,你不能在程序执行时用这种方法分配变量。

示例

void func()
{
	int a;
}
int main()
{
	int b;
	int c[12];
	//...
}

上述代码中所有的变量都是静态分配的。

III - 动态内存分配

那么,既然已经存在一种方式来完成内存分配的工作,为什么我们需要引入另一种分配方法?为什么我们需要在程序执行过程中分配内存?

因为,尽管不是很显而易见,但不能在运行时分配内存,就降低了灵活性,并与空间效率相妥协。特别是,在那些事先不知道输入的情况下,我们会在存储的低效使用和缺乏或过多的空间用来输入数据方面受到影响(给定一个固定长度的数组或类似的数据结构来存储数据)。

所以引入动态内存分配: 在运行时,存储/内存/单元可以分配给变量的机制被称为动态内存分配(不要与 DMA 相混淆)。因此,我们可以知道在运行期间分配内存,这使我们能够使用我们想要的存储,而不用担心任何浪费或者不足。

为什么要使用动态分配的原因

  • 当我们事先不知道程序需要多少内存的时;
  • 当我们希望数据结构没有固定的内存空间上限时;
  • 当你想更有效地使用你的内存空间时。例如: 如果你为一个一维数组分配的内存空间是 array[20],而你最终只使用了 10 个内存空间,那么剩下的 10 个内存空间就被浪费了,这些浪费的内存甚至不能被其他程序变量所使用;
  • 动态创建的列表的插入和删除可以非常容易地通过操作地址来完成,而在静态分配的内存中,插入和删除会导致更多的移动和内存浪费;
  • 当你想在编程中使用结构和链表的概念时,动态内存分配是必须的

C++ 代码

int main(int argc, char* argv[])
{
	// 动态内存分配
	int* ptr = new int;
	int* ptr1 = new int[10];
	// 动态分配内存的释放
	delete ptr;
	delete [] ptr1;
}

C 代码

ptr = calloc(m, n);

等价于

ptr = malloc(m * n);
memset(ptr, 0, m * n);

IV - 小结

有两种类型的可用内存 – 栈 (stack) 和堆 (heap)。静态内存分配只能在栈上进行,而动态内存分配可以在栈和堆上进行。在堆上进行动态分配的一个例子是递归,在递归中,函数按照出现的顺序被放入调用堆,并在到达基数时一个一个地弹出。

当在堆上分配内存时,我们需要手动删除内存,因为即使分配的内存范围结束(如栈的情况),内存也不会被编译器自己释放(取消分配 deallocate)。

4.1 - 静态分配的优缺点

优点

  • 使用简单
  • 分配和取消分配都由编译器完成
  • 高效的执行时间
  • 它使用栈数据结构

缺点

  • 内存浪费问题
  • 必须知道确切的内存需求
  • 一旦初始化后,内存的大小不能调整

4.2 - 动态分配的优缺点

优点

  • 动态分配是在运行时进行的
  • 只要我们需要,我们就可以分配(创建)额外的存储
  • 只要我们使用结束了,内存就可以被取消分配(free / delete)动态空间
  • 因此,人们总是可以准确地拥有所需的空间量–不多也不少。
  • 如果需要,内存大小可以重新分配 

缺点

  • 由于内存是在运行时分配的,因此需要更多的时间。
  • 当完成后,内存需要由用户释放。这一点很重要,因为它更有可能变成难以发现的 bug。

总上所述,静态内存是编译器提前分配的东西。而动态内存是在执行过程中由程序控制的东西。程序可以要求更多的内存,也可以删除部分分配的内存。

到此这篇关于详解C++的静态内存分配与动态内存分配的文章就介绍到这了,更多相关C++ 内存分配内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C语言双指针多方法旋转数组解题LeetCode

    C语言双指针多方法旋转数组解题LeetCode

    这篇文章主要为大家介绍了C语言双指针使用多方法旋转数组题解LeetCode,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步
    2022-02-02
  • c++非变易算法-stl算法

    c++非变易算法-stl算法

    本文主要介绍了C++ STL算法库中的非变易算法,是一些原则上不会变更操作数据的算法,包括:逐个查找算法、元素搜索算法、元素统计算法、序列匹配算法、子序列搜索算法、这些函数均包含于<algorithm>头文件,本文给出的所有代码在VS2010中编译运行通过
    2014-03-03
  • C++数据模型应用在QML委托代理机制中

    C++数据模型应用在QML委托代理机制中

    这篇文章主要介绍了在QML委托代理机制中使用C++数据模型,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-08-08
  • C++设计模式之模板方法模式

    C++设计模式之模板方法模式

    这篇文章主要介绍了C++设计模式之模板方法模式,本文讲解了什么是模板方法模式、模板方法模式的UML类图、模板方法模式的使用场合等内容,需要的朋友可以参考下
    2014-10-10
  • C语言中如何利用循环嵌套输出一个菱形

    C语言中如何利用循环嵌套输出一个菱形

    这篇文章主要介绍了C语言中如何利用循环嵌套输出一个菱形问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-02-02
  • C++插件化 NDD源码的插件机制实现解析

    C++插件化 NDD源码的插件机制实现解析

    这篇文章主要介绍了C++插件化 NDD源码的插件机制实现解析,这里再介绍推荐下优秀的国产软件开源项目 NDD(notepad--),一个支持windows/linux/mac的文本编辑器,目标是要国产替换同类软件,需要的朋友可以参考下
    2023-03-03
  • C语言实践设计开发飞机游戏

    C语言实践设计开发飞机游戏

    飞机大战想必是很多人童年时期的经典游戏,我们依旧能记得抱个老人机娱乐的场景,下面这篇文章主要给大家介绍了关于如何利用C语言写一个简单的飞机大战小游戏的相关资料,需要的朋友可以参考下
    2022-02-02
  • 解析C++中临时对象的产生情况

    解析C++中临时对象的产生情况

    临时对象的产生和销毁都是有成本的,都会影响程序的执行性能和效率,所以如果能了解临时对象产生的原因,就可以提升程序的性能和效率,下面小编就来和大家聊聊临时对象产生的几种情况吧
    2023-06-06
  • Matlab实现遗传算法的示例详解

    Matlab实现遗传算法的示例详解

    这篇文章主要为大家详细介绍了什么是遗传算法,以及如何利用Matlab从零开始自己写一个遗传算法函数,文中的代码对我们学习有一定帮助,需要的可以参考一下
    2022-03-03
  • C++ 中循环链表和约瑟夫环

    C++ 中循环链表和约瑟夫环

    这篇文章主要介绍了C++ 中循环链表和约瑟夫环的相关资料,需要的朋友可以参考下
    2017-06-06

最新评论