【C/C++】如何理解C/C++里的动态内存和资源管理

在写程序的时候,我们最关心的事情是什么?关心程序会不会出bug!!哈哈,开个小玩笑,但是往往我们在写一个程序时确实是非常关心程序会不会在运行时崩溃,或者编译时出错等问题,但是最关心的还是内存和资源管理了。
如果没有内存,程序恐怕也是没有意义的。就像你面前有一盘极其美味的食物,但是你的胃已经装满了大馒头,你也是吃不下的。
C语言和C++提供了不同的动态内存管理,可以让我们在写程序的时候,能够根据程序的需求开辟不同的空间,不至于浪费太多的空间,毕竟内存的资源还是有限的,不会让我们取之不尽用之不竭。
首先我们来看看一张思维导图

这里写图片描述

从上面的图里我们可以看到C和C++里的动态内存管理的关键字和特点是不同的。
注意图里的用虚线框起来的两两关键字是要配套使用的,否则可能会造成内存泄漏。

特别要注意的是,在开辟空间时,系统不会真的给你你需要的那么多字节(或者说是空间),有可能会给的比你要的多,但是你并不知道。

如果我们不知道开的空间到底是多大,那释放的时候会不会少释放然后造成内存泄露吗?实际上是我们想多了,既然它多开辟的空间不会让我们知道,那么在我们不知道的地方也会将这些多开辟的空间释放掉。但是我们必须要明白这是如何做到的,以防止编程时遇到类似问题却不知如何下手。
请看图:
这里写图片描述

由此我们可以看出实际上内存管理器分配出来的空间要比我们需要的要多,但是返回给我们的却是我们需要的字节数。在大小这个框里,它一般是一个指针的大小,即四个字节,所以在释放时我们会向前加上四个字节,以便释放所有空间。

那么代码是如何实现的呢?

//注意关键字匹配使用
int main()
{
    {
        int* p1 = new int; // 动态分配4个字节(1个 int)的空间单个数据
        int* p2 = new int(10); // 动态分配4个字节(1个 int)的空间并初始化为10
        int* p3 = new int[10]; // 动态分配40个字节(10个 int)的空间
        delete p1;
        delete p2;
        delete[] p3;
    system("pause");
    return 0;
}

通常情况下我们关心的是一个程序干了件什么事,对于new来说,它在开辟空间的时候还做了一件事,那就是调用构造函数进行初始化。而delete,则是在清理空间的同时调用析构函数来清理空间。

那么对于new[N]以及delete[]又干了什么样的事情??

与new不同的是:new[N]会调用N次构造函数来初始化列表

与delete不同的是:delete[]会调用N次析构函数来清理空间

敲黑板

为什么delete没有传参它就知道要清理(释放)N次??

这里写图片描述

好了,这个图很清晰的解释了。

如此我们知道在new数组的时候好像要复杂那么一些些,我们可以用宏来模拟实现以下new
delete以及new[],delete[]。

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<stdlib.h>
using namespace std;

//宏实现new和delete
#define NEW(ptr,type,n)                             \
    ptr = (type*) operator new (sizeof(type)*n);    \
    new(ptr)type;

#define DELETE(ptr,type)    \
do{                         \
    ptr->~type();          \
     operator delete(ptr);  \
} while (0)


//宏实现new[]和delete[]
#define NEW_ARRAY(ptr,type,n)                       \
    do{                                             \
        ptr = (type*)malloc(sizeof(type)*n + 4);    \
        (*(int*)ptr) = n;                           \
    for (size_t i = 0; i < n; i++)                  \
        new (ptr + i) type;                         \
    } while (0)

#define DELETE_ARRAY(ptr,type,n)                    \
    do{                                             \
    for (size_t i = 0; i < n; i++)                  \
        (ptr+i)->~type();                          \
    operator delete(ptr);                           \
    }while (0)


class test
{

public :
    test(char* s = "") :_s(new char[strlen(s)])
    {
    }
    ~test()
    {
        delete _s;
    }
private:
    char* _s;
};
int main()
{
    test* s = NULL;
    NEW_ARRAY(s, test, 6);
    DELETE_ARRAY(s, test, 6);
    NEW(s, test, 6);
    DELETE(s, test);
    system("pause");
    return 0;
}

C语言和C++的内存管理是非常的重要的,有时候一些bug会从中产生,如果我们清楚这些原理就能很容易的修改bug。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值