• new,delete和malloc,free以及allocator<T>


    一)new和delete,自己觉得一句话就是:最好同一作用域内,必须成对使用

    先给出自己的认识:

    malloc,free,申请和释放一段heap堆中的内存。

    new:申请heap内存并在申请的内存中放置用默认构造函数构造好的对象。(注意:对象内可能也有申请堆内存,new)

    delete:完成了两个工作,

    1. 释放对象内申请的堆内存。 所以会去调用析构函数。

    2. 释放对象本身占用的堆内存。类似free 对象指针。

    如下例子,明白了,就应该基本初步认识了new和delete。

    #include <stdio.h>
    #include <iostream>
    using namespace std;
    
    class myclass
    {
    public:
        myclass(const string& _name,const string& _des):name(_name),heaporstack(_des)
        {
            pint=new int[10]{1,2,3,4,5,6,7,8,9,0};
            printf("%s  Construt by %s. add of class:%0x. add of int[] in class:%0x0 
    ",name.c_str(),heaporstack.c_str(), this,pint);
        };
        ~myclass()
        {
            delete[] pint;
            printf("%s  Destory  by %s. add of class:%0x. add of int[] in class:%0x0 
    ",name.c_str(),heaporstack.c_str(), this,pint);
        }
        string name;
        string heaporstack;
        int * pint;
    
    private:
        myclass(){}
    };
    
    int main()
    {
        myclass Mclass_local("Mclass_local","stack");
    
    
        myclass* Mclass_heap=new myclass("Mclass_heap","heap");
        delete Mclass_heap;
        Mclass_heap=0x0;
        return 0;
    }

    所以,使用基本原则:

    1)成对使用。new 对 delete . new a[]  对 delete [] a;

    2)谁new谁delete。 mian方法中,new,那么main必须delete。 class 中new。那么class的析构函数~class{delete} 最好有delete。也就是最好同一作用域内。

    3)delete后,必须把指针设置为空指针。当然在析构函数内其实不用写。因为析构是最后执行的,类里面不太会有语句在析构之后执行。

    二)C++还有一个std::allocator<T>

    作用:某些类,需要预先分配用于创建新对象的内存,需要时再在预先分配的内存中构造新对象。也就是以空间换时间的策略。

    比如vector。就是典型的这种类,先分配一定大小,加入数据时,如空间够,不必要每次插入数据就申请一次空间,只有空间不够才再次申请原空间的2倍内存。典型的预支内存空间换申请内存时间的策略。

    常用的操作:

    allocator<T> a;    定义一个T类型的allocator对象。

    a.allocate(n);       申请n个T大小的,未分配的空间。类似(T*) malloc(sizeof(T)*n)

    a.deallocate(p,n)  释放内存,p为T*,n为释放的T类型对象的数量。注意:T类型对象本身,如有需要释放的资源,必须先释放,a.deallocate(p,n)只是释放对象本身的内存,而对象的建立又额外申请的资源,需要另外处理。

    a.construct(p,t)   复制构造,用t来复制构造。相当于 new (p) T(t),这个是placement new的用法  new(place_address) type(initializer-list)

    uninitialized_copy(startit,endit,it)   startit,endit :要复制的开始迭代器地址和结束地址。it:要复制的迭代器地址。

      (迭代器指向的类型是POD型别,不用构造,可以直接拷贝,不清楚具体处理,见链接,备了解。)

    uninitialized_fill(startit,endit,obj)     startit,endit :要复制的开始迭代器地址和结束地址。it:要复制的对象。 使用复制构造函数填充内存

    uninitialized_fill_n(startit,endit,obj,n)     startit,endit :要复制的开始迭代器地址和结束地址。it:要复制的对象。 n,要复制的数量。 使用复制构造函数填充内存

  • 相关阅读:
    JavaScript中的prototype
    SQL 时间格式转换
    ASP.NET MVC自定义视图引擎ViewEngine 创建Model的专属视图
    JavaScript事件使用指南
    30行代码实现JavaScript中的MVC
    JavaScript中this指针指向的彻底理解
    JavaScript 中的命名空间
    C#嵌套类型
    C# 为枚举创建新方法
    Lambda 表达式
  • 原文地址:https://www.cnblogs.com/lsfv/p/6006860.html
Copyright © 2020-2023  润新知