• c++动态内存管理


    我们都知道在c++中能够用new/malloc动态分配内存空间用delete/free释放动态开辟的内存空间。

    c++中的malloc/free是继承c语言中的malloc/free。它的使用方法和在C语言中的使用方法一模一样。

    1.那么既然c++中有了能够动态开辟内存的函数为什么又要有new/delete呢?

    我们知道malloc仅仅是单纯的开辟内存空间而不进行初始化,free仅仅是将动态开辟的内存空间给释放了。

    对于内置类型而言。用malloc/free开辟和释放内存没有一点问题,可是对于非内置类型来说,因为对象在创建的时候要调用构造函数进行初始化。而在对象在消亡的时候要调用析构函数进行一些清理工作,显然,malloc/free无法完毕这些事情。

    因此,c++中提供了new/delete两个操作符。用new在动态分配内存的时候调用构造函数进行初始化,delete在释放内存的时候自己主动调用析构函数进行清理。

    2.new/delete的使用方法

    A为非内置类型

    class A
    {
    public:
         A(int a=0,int b=0)
       :_a(a)
       ,_b(b)
         {
              cout << "A()"<<endl;
         }
         ~A()
         {
              cout << "~A()" << endl;
         }
    private:
         int _a;
    };

    wKiom1baxwziKipDAAAt-y6Xi2g477.png

    注意:

    new和delete。new[]和delete[]一定要成对出现,在以下我们会解释为什么new[]和delete[]要成对出现。

    3.new和delete的内部实现:

    通过跟踪调试程序,我们能够知道new和delete内部是通过调用一些函数实现的。

    new内部是通过调用以下函数实现的

    char *  operatoer new(size_t count);

    char * operator new[](size_t count);

    详细调用顺序例如以下:wKiom1ba0yPysAAHAAAb5mp9tP4231.png

    delete内部是通过调用以下两个函数实现的:

    void operator delete(char *p);

    void operator delete(char *p);

    详细调用顺序例如以下:

    wKioL1ba1mOgp5-zAAAeNXaA7Hg963.png

    4.new和delete,new[]和delete[]为什么要成对出现?

    1.malloc/free为防止内存泄漏,一定要成对出现。

    2.new和delete成对出现的原因则是因为new开辟内存空间是调用构造函数创建对象,而假设不用delete释放空间而是用free,那么释放空间之前不会运行析构函数。有可能会导致内存泄漏。、

    A *pa=new A;

    free(pa);//错误

    delete pa;//正确

    3.new[]和delete[]为什么要成对出现呢?我们通过运行程序能够发现:

    1.当我们用new[]开辟10个连续内置类型空间,而用delete释放。这时运行程序。程序不会崩溃。

    int *p=new int[10];

    delete p;

    2.当我们用new[]开辟10个连续的非内置类型的空间。没实用delete[]释放。运行程序时,程序会崩溃。

    A* pa=new A[10];

    delete pa;

    这是为什么呢?

    当我们运行以下的程序,

    我们发现运行

    int *p=new int[10]开辟内存时传给operator new[](size_t count)的count是40。

    wKioL1ba3Q3TAZmuAAAoB9dGhRk203.png

    A* pa=new A[10]开辟内存时传给operator new[](size_t count)的count是84。

    wKioL1ba3cSQb8jhAAApUDDFiws961.png

    这就说明了new在开辟内置类型的空间时,开辟得空间数量是指定的空间数量,字节数是指定的数量乘以类型的大小。

    而在开辟非内置类型空间时,除了开辟指定数量的空间以外。还多开辟4个字节的空间。

    new开辟非内置类型的空间时传给operator new[](size_t count)的count是类型的大小*空间的数量在加上4个字节。最前面的空间里放的是要运行析构函数的次数。它返回给a2的地址是最前面的空间的后一个空间的地址。

    wKioL1ba-V-QvSurAAA2epw540M785.png

    wKiom1ba9MLRKqlOAAAhGuT0CQ4327.png

    因为内置类型没有析构函数,因此没有多开辟空间。

    非内置类型用delete[]在释放空间时调用operator delete[](char *p),而此时的p被编译器内部处理过后,它指向的是这些连续空间的最前面一个空间的地址。因此。而传给operator delete(char *p)的地址是处理过后的地址,因此,他能够释放一块连续的空间而且直到调用析构函数的次数。

    而假设用delete。则直接调用operator delete(char *p),传给p的地址是a2的地址,假设释放它,就相当于释放动态开辟空间的一部分,这样会造成内存泄露。使程序崩溃,而编译器不知道调用多少次析构函数。

  • 相关阅读:
    PHP发送邮件(php100视频后笔记)
    简单页面访问统计
    怎样制作RSS源
    r给自己网站/博客制作安卓应用程序
    反射简单概念
    笔记本
    使用IHttpModule实现简单的页面重映射Url
    工厂方法模式与抽象工厂模式的区别
    安装TFS2010实际体验
    限定登录失败次数,超过指定次数就限制登录一段时间
  • 原文地址:https://www.cnblogs.com/tlnshuju/p/7401346.html
Copyright © 2020-2023  润新知