【C/C++】 静态内存分配与动态内存分配

简介: C/C++ 中静态内存分配与动态内存分配相关内容,区别与比较

【C/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 相混淆)。因此,我们可以知道在运行期间分配内存,这使我们能够使用我们想要的存储,而不用担心任何浪费或者不足。

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

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

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。

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

目录
相关文章
|
2月前
|
安全 C语言 C++
比较C++的内存分配与管理方式new/delete与C语言中的malloc/realloc/calloc/free。
在实用性方面,C++的内存管理方式提供了面向对象的特性,它是处理构造和析构、需要类型安全和异常处理的首选方案。而C语言的内存管理函数适用于简单的内存分配,例如分配原始内存块或复杂性较低的数据结构,没有构造和析构的要求。当从C迁移到C++,或在C++中使用C代码时,了解两种内存管理方式的差异非常重要。
127 26
|
7月前
|
存储 程序员 编译器
玩转C++内存管理:从新手到高手的必备指南
C++中的内存管理是编写高效、可靠程序的关键所在。C++不仅继承了C语言的内存管理方式,还增加了面向对象的内存分配机制,使得内存管理既有灵活性,也更加复杂。学习内存管理不仅有助于提升程序效率,还有助于理解计算机的工作原理和资源分配策略。
|
3月前
|
C语言 C++
c与c++的内存管理
再比如还有这样的分组: 这种分组是最正确的给出内存四个分区名字:栈区、堆区、全局区(俗话也叫静态变量区)、代码区(也叫代码段)(代码段又分很多种,比如常量区)当然也会看到别的定义如:两者都正确,记那个都选,我选择的是第一个。再比如还有这样的分组: 这种分组是最正确的答案分别是 C C C A A A A A D A B。
60 1
|
9月前
|
存储 缓存 编译器
【硬核】C++11并发:内存模型和原子类型
本文从C++11并发编程中的关键概念——内存模型与原子类型入手,结合详尽的代码示例,抽丝剥茧地介绍了如何实现无锁化并发的性能优化。
401 68
|
6月前
|
存储 Linux C语言
C++/C的内存管理
本文主要讲解C++/C中的程序区域划分与内存管理方式。首先介绍程序区域,包括栈(存储局部变量等,向下增长)、堆(动态内存分配,向上分配)、数据段(存储静态和全局变量)及代码段(存放可执行代码)。接着探讨C++内存管理,new/delete操作符相比C语言的malloc/free更强大,支持对象构造与析构。还深入解析了new/delete的实现原理、定位new表达式以及二者与malloc/free的区别。最后附上一句鸡汤激励大家行动缓解焦虑。
|
7月前
|
安全 C语言 C++
彻底摘明白 C++ 的动态内存分配原理
大家好,我是V哥。C++的动态内存分配允许程序在运行时请求和释放内存,主要通过`new`/`delete`(用于对象)及`malloc`/`calloc`/`realloc`/`free`(继承自C语言)实现。`new`分配并初始化对象内存,`delete`释放并调用析构函数;而`malloc`等函数仅处理裸内存,不涉及构造与析构。掌握这些可有效管理内存,避免泄漏和悬空指针问题。智能指针如`std::unique_ptr`和`std::shared_ptr`能自动管理内存,确保异常安全。关注威哥爱编程,了解更多全栈开发技巧。 先赞再看后评论,腰缠万贯财进门。
340 0
|
8月前
|
存储 程序员 编译器
什么是内存泄漏?C++中如何检测和解决?
大家好,我是V哥。内存泄露是编程中的常见问题,可能导致程序崩溃。特别是在金三银四跳槽季,面试官常问此问题。本文将探讨内存泄露的定义、危害、检测方法及解决策略,帮助你掌握这一关键知识点。通过学习如何正确管理内存、使用智能指针和RAII原则,避免内存泄露,提升代码健壮性。同时,了解常见的内存泄露场景,如忘记释放内存、异常处理不当等,确保在面试中不被秒杀。最后,预祝大家新的一年工作顺利,涨薪多多!关注威哥爱编程,一起成为更好的程序员。
328 0
|
10月前
|
大数据 C语言
C 语言动态内存分配 —— 灵活掌控内存资源
C语言动态内存分配使程序在运行时灵活管理内存资源,通过malloc、calloc、realloc和free等函数实现内存的申请与释放,提高内存使用效率,适应不同应用场景需求。
|
10月前
|
容器
在使用指针数组进行动态内存分配时,如何避免内存泄漏
在使用指针数组进行动态内存分配时,避免内存泄漏的关键在于确保每个分配的内存块都能被正确释放。具体做法包括:1. 分配后立即检查是否成功;2. 使用完成后及时释放内存;3. 避免重复释放同一内存地址;4. 尽量使用智能指针或容器类管理内存。
|
10月前
|
存储 缓存 C语言
【c++】动态内存管理
本文介绍了C++中动态内存管理的新方式——`new`和`delete`操作符,详细探讨了它们的使用方法及与C语言中`malloc`/`free`的区别。文章首先回顾了C语言中的动态内存管理,接着通过代码实例展示了`new`和`delete`的基本用法,包括对内置类型和自定义类型的动态内存分配与释放。此外,文章还深入解析了`operator new`和`operator delete`的底层实现,以及定位new表达式的应用,最后总结了`malloc`/`free`与`new`/`delete`的主要差异。
180 3