【两周学完C++】DAY2_内存分配方式与堆内存管理(new、delete关键字)

C++ 程序在运行时,计算机内存被分为程序代码区、全局数据区、堆区、栈区四个部分。

本文一是介绍 C++ 三种内存分配方式,二是使用 new 关键字delete 关键字管理堆内存

C语言堆区内存管理移步:【堆区内存管理】堆区(heap)内存操作: malloc()calloc()memcpy()memset()free() 函数操作堆区内存

目录

  1. 内存分配的三种方式

静态存储分配
内存分配
内存分配

  1. C++堆内存管理

new 关键字
delete 关键字

1. 内存分配的三种方式

不同的内存分配方式,有不同的内存调度机制。

C++ 语言的三种内存分配方式分别是:静态存储区分配、栈内存分配和堆内存分配

1.1 静态存储区分配
  • 定义:在程序编译时分配的内存,存在于程序的整个运行过程

    例如: static 变量,其生命周期随程序的结束而结束,而非像一般变量随函数或作用域的结束而结束。

    除了 static 变量,还有一种全局对象 static object,也可以存放在静态存储区。

1.2 栈内存分配
  • 定义:内存是存在于某作用域(局部变量)的一块空间,函数调用时分配栈内存,按照后进先出(LIFO)原则管理。

  • 生命周期:起于变量声明,止于函数执行结束

    例如:调用某个函数时,函数内局部变量的存储单元可以在栈上创建,函数执行结束时,这些内存单元会被自动释放;

  • 特点

    • 自动管理:栈内存的分配和释放由编译器自动管理,无需程序员手动干预。
    • 存储限制:栈的大小通常有限,过多的局部变量可能导致栈溢出。
  • 内存位置:存放在栈区,栈区位于内存的高地址区域。

1.3 堆内存分配
  • 定义:也称 动态内存分配,使用 malloccallocreallocfree(C)或 newdelete(C++)进行管理。

  • 生命周期:用户可以手动分配和释放内存,生存周期由用户决定,灵活性高。

  • 特点

    • 灵活性:可以根据需要动态调整内存大小。
    • 内存碎片:频繁的分配和释放可能导致内存碎片,影响性能。
    • 手动管理:需要程序员显式释放不再使用的内存,避免内存泄漏。
  • 内存位置:存放在堆区,通常在内存的中间区域。

1.4 总结
  • 静态存储区分配适合不需要改变的全局或静态变量,生命周期长。
  • 栈内存分配适用于局部变量,自动管理,使用方便,但空间有限。
  • 堆内存分配灵活性高,适合动态需求,但需要手动管理内存。

2. C++堆内存管理

C 语言: malloc() 函数来分配内存空间,free() 函数来释放内存空间。

C++ 语言: new 关键字来分配内存空间,delete 关键字来释放内存空间。后者在性能等方面优于前者

在学习使用 new 和 delete 关键字之前我们先初步了解一下指针的概念及其一般形式

2.1 预知:指针

指针是一个变量,其值是另一个变量的地址。指针变量声明的一般形式为:

type *pointerVar-name

其中 type 为指针的数据类型,* 是定义指针的关键符,pointerVar-name 指定指针变量名。

例如:char *p,即定义了一个字符型指针变量 p。

指针的另一些基本内容会在后续的实验中详细介绍,本次实验对指针的内容仅做了解。现在我们正式学习 new 关键字和 delete 关键字。

2.2 new 关键字

new 关键字 用于堆内存的分配,可自动计算所要分配内存空间的大小,其基本使用形式为:

指针变量名 = new 类型

例如:

int *p; //定义一个整型指针变量
p = new int;

其中 p = new int; 表示动态分配一个存放整型数据的内存空间,并将其首地址赋给整型指针变量 p,此时省略指针变量 p 前的 *

2.3 delete 关键字

delete 关键字 用于堆内存的释放,其基本形式为:

delete 指针变量

例如:

int *p; //定义一个整型指针变量
p = new int;
//省略指针操作过程
delete p;

其中 delete p; 表示释放指针变量 p 指向的内存空间,此时省略指针变量 p 前的 *

注意:使用 new 获取的内存空间必须使用 delete 进行释放。

我们用实例来加深一下 new 和 delete 关键字的使用方式,新建 mans.cpp 文件,输入:

#include <iostream>
using namespace std;

int main()
{
    int *p; //定义一个整型的指针变量 p。
    p = new int; //动态分配一个存放整型数据的内存空间,并将其首地址赋给整型指针变量 p。
    *p = 6; //为指针指向的内存块赋值为 6。
    cout<<*p<<endl; //输出内存块的赋值。
    delete p;//释放指针变量 p 指向的内存空间。
    return 0;
}

程序首先定义了整型指针变量 p,然后使用 new 关键字为其分配 int 型的内存空间,并让指针 p 指向分配的内存空间。随后为内存块赋值为 6,并且输出所赋的值。最后释放指针变量 p。

程序结果为:

name: 检查目录是否创建
  script: |
    #!/bin/bash
    ls /home/project/mans.cpp
  error: 未创建 mans.cpp 文件
  timeout: 1
- name: 检查文件内容
  script: |
    #!/bin/bash
    grep delete /home/project/mans.cpp
  error: 内存分配有误
  timeout: 2