细说C++(十七):new与delete解析(一)

动态内存分配

  • new分配动态内存
    :使用自由空间分配得内存是无名的,因此new无法为其分配的对象命名,而是返回一个指向一个该对象指针.

  • delete释放动态内存
    :堆区分配内存,必须手动释放,避免内存泄漏

    :原型

void *operator new(size_t);     //allocate an object
void *operator delete(void *);    //free an object

void *operator new[](size_t);     //allocate an array
void *operator delete[](void *);    //free an array

(new和delete 为C++ 定义的关键字,通过特定的语法可以组成表达式)

底层解析
:举例

class A
{
public:
    A(int v) : var(v)
    {
        fopen_s(&file, "test", "r");
    }
    ~A()
    {
        fclose(file);
    }

private:
    int var;
    FILE *file;
};

,类 A 中有两个私有成员,有一个构造函数和一个析构函数,构造函数中初始化私有变量 var 以及打开一个文件,析构函数关闭打开的文件。

new

class A *pA = new A(10);

创建一个类的对象,返回其指针 pA。如下图所示 new 背后完成的工作:

在这里插入图片描述

new底层可解析为三步

(1)首先需要调用上面提到的 operator new 标准库函数,传入的参数为 class A 的大小,这里为 8 个字节,至于为什么是 8 个字节,你可以看看《深入 C++ 对象模型》一书,这里不做多解释。这样函数返回的是分配内存的起始地址,这里假设是 0x007da290。
(2)上面分配的内存是未初始化的,也是未类型化的,第二步就在这一块原始的内存上对类对象进行初始化,调用的是相应的构造函数,这里是调用 A:A(10); 这个函数,从图中也可以看到对这块申请的内存进行了初始化,var=10, file 指向打开的文件。
(3)最后一步就是返回新分配并构造好的对象的指针,这里 pA 就指向 0x007da290 这块内存,pA 的类型为类 A 对象的指针。

delete

delete pA;

在这里插入图片描述

delete 底层分解两步:

(1)调用 pA 指向对象的析构函数,对打开的文件进行关闭
(2)通过上面提到的标准库函数 operator delete 来释放该对象的内存,传入函数的参数为 pA 的值,也就是 0x007d290

那么 delete pA; 做了两件事:

调用一次 pA指向的对象的析构函数;
调用 operator delete(pA); 释放内存

申请和释放数组

string *psa = new string[10];      //array of 10 empty strings
int *pia = new int[10];           //array of 10 uninitialized ints

delete [] psa;
delete [] pia;

注意:(new)上面在申请一个数组时都用到了 new [] 这个表达式来完成,按照我们上面讲到的 new 和 delete 知识,
第一个数组是 string 类型,分配了保存对象的内存空间之后,将调用 string 类型的默认构造函数依次初始化数组中每个元素;
第二个是申请具有内置类型的数组,分配了存储 10 个 int 对象的内存空间,但并没有初始化。

(delete)都用到 delete [] 表达式,注意这地方的 [] 一般情况下不能漏掉!
我们也可以想象这两个语句分别干了什么:第一个对 10 个 string 对象分别调用析构函数,
然后再释放掉为对象分配的所有内存空间;第二个因为是内置类型不存在析构函数,直接释放为 10 个 int 型分配的所有内存空间。

new[ ]

class A *pAa = new A[3];

在这里插入图片描述

delete[ ]

delete []pAa;

在这里插入图片描述

注意两点是:

(1)调用析构函数的次数是从数组对象指针前面的 4 个字节中取出;
(2)传入 operator delete[] 函数的参数不是数组对象的指针 pAa,而是 pAa 的值减 4。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值