三、动态内存#

1. 内存分区#

在C++中内存分为5个区,分别是全局/静态存储区代码|常量存储区| 共享内存区

栈区:又叫堆栈,存储非静态局部变量、函数参数、 返回值等,栈是可以向下生长的

共享内存区:是高效的I/O映射方式,用于装载一个共享的动态内存库。用户可使用系统接口创建共享共享内 存,做进程间通讯

堆区:用于程序运行时动态内存分配,堆是可以向上增长的

静态区:存储全局数据和静态数据

代码区:存储可执行的代码、只读常量

2. new 和 delete#

在 c++ 中 , 如果要在堆内存中申请空间,那么需要借助 new 操作符,释放申请的空间,使用 delete操作 。而c语言使用的是mallocfree ,实际上newdelete 的底层实际上就是 mallocfree

1. new#

在c++中, new是一个关键字,同时也是一个操作符,用于在堆区申请开辟内存 , new的操作还具备以下几个特征:

  1. 内存申请成功后,会返回一个指向该内存的地址。
  2. 若内存申请失败,则抛出异常,
  3. 申请成功后,如果是程序员定义的类型,会执行相应的构造函数
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>

using namespace std;

class stu{

    stu(){
        cout << "执行构造函数" <<endl;
    }

    ~stu(){
        cout << "执行析构函数" <<endl;
    }

}


int main(){
    int *a = new int();
    stu *s = new stu();

    //new的背后先创建
    return 0 ;
}

2. delete#

在c++中,deletenew 是成对出现的,所以就有了no new no delete的说法。delete用于释放new 申请的内存空间。 delete 的操作具备以下几个特征:

  1. 如果指针的值是0 ,delete不会执行任何操作,有检测机制
  2. delete只是释放内存,不会修改指针,指针仍然会指向原来的地址
  3. 重复delete,有可能出现异常
  4. 如果是自定义类型,会执行析构函数
1
2
3
4
5
6
7
8
int main(){

    int *p = new int(6);
    delete p ; // 回收数据

    *p = 18 ; //依然可以往里面存值,但是不建议这么做。
    return 0 ;
}

3. malloc 和 free#

malloc` 和 free 实际上是C语言 申请内存的语法,在C++ 也得到了保存。只是与 new 和 delete 不同的是, 它们 是函数,而 new 和 delete是作为关键字使用。 若想使用,需要导入`#include

  • malloc
  1. malloc 申请成功之后,返回的是void类型的指针。需要将void*指针转换成我们需要的类型。1.
  2. malloc 要求制定申请的内存大小 , 而new由编译器自行计算。
  3. 申请失败,返回的是NULL , 比如: 内存不足。
  4. 不会执行自定义类型的构造函数
1
2
3
4
5
int main(){

    int *p=(int *)malloc(int); //如果申请失败,返回的是NULL
    return 0 ;
}
  • free

free 和 malloc是成堆出现的,所以也有了 no malloc no free的说法。 free 用于释放 mallo申请的内存空间。

  1. 如果是空指针,多次释放没有问题,非空指针,重复释放有问题
  2. 不会执行对应的析构
  3. delete的底层执行的是free
1
2
3
4
5
6
7
int main(){

    int *p=(int *)malloc(int); //如果申请失败,返回的是NULL

    free(p);
    return 0 ;
}