C/C++内存管理--1

简介: C/C++内存管理--1

一,C/C++内存分布

内存区域的大概介绍:


       C/C++中,我们目前需要了解的内存区域是栈区、堆区、静态区、常量区。其中,栈区用于临时存储数据,如函数的栈帧,局部变量等。堆区一般用来存储动态开辟的空间,如malloc、calloc、realloc、new等开辟的空间。静态区原名是代码段,一般存储全局变量和静态数据,在整个程序都可以使用。常量区用来存储常量,如字面量等。这些东西之前有过说明,这里我们简单提一下即可。


65e1dd660fef4b268805f51f0df4c537.png


       以上东西全为基础,接下来我们来看看以下代码中的数据的存储空间。


int globalVar = 1;
static int staticGlobalVar = 1;
void Test()
{
    static int staticVar = 1;
    int localVar = 1;
    int num1[10] = { 1, 2, 3, 4 };
    char char2[] = "abcd";
    const char* pChar3 = "abcd";
    int* ptr1 = (int*)malloc(sizeof(int) * 4);
    int* ptr2 = (int*)calloc(4, sizeof(int));
    int* ptr3 = (int*)realloc(ptr2, sizeof(int) * 4);
    free(ptr1);
    free(ptr3);
}
选项 : A.栈  B.堆  C.数据段(静态区)  D.代码段(常量区)
globalVar在   C      staticGlobalVar在  C
staticVar在    C       localVar在    A
num1 在     A
char2在      A          * char2在    A
pChar3在   A         * pChar3在   D
ptr1在   A               * ptr1在   B

分析:前5个好理解,要注意的是后面六个选项。char2在函数栈帧中创建了一个数组,其代表了首元素的地址,存储在栈区中,而*char2代表首元素,也存储在栈区中。pChar3要注意的是,这里的const修饰的是*pChar3,即 "abcd" 是一个字面量,存储在常量区中,而pChar3是一个指针,存储在栈区中。ptr1的类型是int* ,指向堆区中开辟动态空间的首地址,因此,ptr1存储在栈区中,*ptr1指向数据,存储在堆区中。



805745e0d2464eaf87a531d07e6d1611.png

二,C++动态开辟空间

1,new/delete操作内置类型

       我们都知道,C语言中有malloc、calloc、realloc、free语法进行动态空间的管理,而C++中通过new和delete操作符进行动态空间管理。其中new用来开辟空间,delete用来释放空间。其中,new可以对创建的空间进行初始化。


//动态开辟一个int型的空间
int* p1 = new int;//里面是随机值,不会初始化
int* p2 = new int(1);//动态开辟一个空间并初始化为1
//动态开辟多个int型的空间
int* p3 = new int[5]{ 1, 2 };//动态开辟5个空间并初始化为1 2 0 0 0 
int* p4 = new int[10];//里面是随机值,不会初始化
//删除开辟一个空间
delete p1;
delete p2;
//删除开辟多个空间
delete[] p3;
delete[] p4;

       注意:C++中delete在释放中不支持一次多次释放,如下:


//下面是错误的用法
delete p1,p2;
delete[] p3,p4;


       new操作符在没有指定初始化的时候系统不会自动初始化。


#include <iostream>
#include <string>
using namespace std;
int main()
{
    int n = 2;
    int* a = new int[n];
    a[0] = 0;
    a[1] = 1;
    a = new int[2 * n];//重新分配空间大小,里面全部是随机值
    return 0;
}

2,new和delete操作自定义类型

       这里要说明的是,操作自定义时,new/delete 和 malloc/free的最大区别是 new/delete对于【自定义类型】除了开空间还会调用构造函数和析构函数进行空间的初始化和释放。


class A
{
public:
    A(int a = 0)
        : _a(a)
    {
        cout << "A():" << this << endl;
    }
    ~A()
    {
        cout << "~A():" << this << endl;
    }
private:
    int _a;
};
int main()
{
    //通过调试可见,动态开辟空间初始化过程中调用了构造函数
    //只调用一次构造函数
    A* p1 = new A;
    A* p2 = new A(1);
    A aa1(1);
    A aa2(1);
    A aa3(1);
    //调用了三次构造函数
    A* p3 = new A[3]{ aa1, aa2, aa3 };
    A* p4 = new A[3]{A(2), A(2), A(2) };
    A* p5 = new A[3]{ 3, 3, 3 };
    //通过调试可见,动态空间释放过程中调用了析构函数
    //只调用一次析构函数
    delete p1;
    delete p2;
    //调用了三次析构函数
    delete[] p3;
    delete[] p4;
    delete[] p5;
    return 0;
}

总的来说:


       new的本质:开空间+调用构造函数初始化。


       delete的本质:调用析构函数释放空间。


       通过以上可总结出,在开辟和释放的过程中,new关键字开辟了多少个动态类型空间,将会调用多少次构造函数;delete关键字释放了多少个动态类型空间,将会调用多少次析构函数。其中new开辟的空间无论是否进行初始化,构造函数都会被调用。


C/C++内存管理--2https://developer.aliyun.com/article/1424646?spm=a2c6h.13148508.setting.20.214f4f0eqBSn46

相关文章
|
19天前
|
C++
【C++】深入解析C/C++内存管理:new与delete的使用及原理(二)
【C++】深入解析C/C++内存管理:new与delete的使用及原理
|
19天前
|
编译器 C++ 开发者
【C++】深入解析C/C++内存管理:new与delete的使用及原理(三)
【C++】深入解析C/C++内存管理:new与delete的使用及原理
|
14天前
|
存储 程序员 编译器
简述 C、C++程序编译的内存分配情况
在C和C++程序编译过程中,内存被划分为几个区域进行分配:代码区存储常量和执行指令;全局/静态变量区存放全局变量及静态变量;栈区管理函数参数、局部变量等;堆区则用于动态分配内存,由程序员控制释放,共同支撑着程序运行时的数据存储与处理需求。
58 21
|
2天前
|
程序员 C++ 容器
在 C++中,realloc 函数返回 NULL 时,需要手动释放原来的内存吗?
在 C++ 中,当 realloc 函数返回 NULL 时,表示内存重新分配失败,但原内存块仍然有效,因此需要手动释放原来的内存,以避免内存泄漏。
|
5天前
|
存储 C语言 C++
【C++打怪之路Lv6】-- 内存管理
【C++打怪之路Lv6】-- 内存管理
23 0
【C++打怪之路Lv6】-- 内存管理
|
15天前
|
存储 C语言 C++
【C/C++内存管理】——我与C++的不解之缘(六)
【C/C++内存管理】——我与C++的不解之缘(六)
|
17天前
|
程序员 C语言 C++
C++入门5——C/C++动态内存管理(new与delete)
C++入门5——C/C++动态内存管理(new与delete)
48 1
|
17天前
|
编译器 C语言 C++
详解C/C++动态内存函数(malloc、free、calloc、realloc)
详解C/C++动态内存函数(malloc、free、calloc、realloc)
71 1
|
19天前
|
存储 安全 程序员
【C++篇】深入内存迷宫:C/C++ 高效内存管理全揭秘
【C++篇】深入内存迷宫:C/C++ 高效内存管理全揭秘
51 3
|
10天前
|
C++
C/C++内存管理(下)
C/C++内存管理(下)
24 0