• C++中关于new及动态内存分配的思考


    如何实现一个malloc?

    malloc_tutorial.pdf

    ————————————————————————————————————

        我们知道,使用malloc/calloc等分配内存的函数时,一定要检查其返回值是否为“空指针”(亦即是检查分配内存的操作是否成功),这是良好的编程习惯,也是编写可靠程序所必需的。但是,如果你简单的把这一招应用到new上,那就不一定正确了。

        C++里,如果new分配内存失败,默认是抛出异常的如果你想检查new是否成功,应该捕捉异常。

        try{
            int* p = new int[SIZE];
            //其他代码
        }catch( const bad_alloc& e ){
            return -1;
        }

    当然,标准的C++亦提供了一个方法来抑制new抛出异常,而返回空指针:

        int* p = new (std::nothrow) int; //这样,如果new失败了,就不会抛出异常,而是返回空指针
            if( p==0 )//如此这般,这个判断就有意义了
                return -1//其他代码

    ——————————————————————以上都是无用之谈

    new的语法格式:new 数据类型(初始化参数列表);

    关于new后加()与不加()的区别:

      在用new建立一个类的对象时,若存在用户定义的默认构造函数,则new T和new T()两写法效果相同,都会调用此默认构造函数;若未定义,new T会调用系统默认构造函数,new T()除了调用系统默认构造函数,还会给基本数据类型和指针类型的成员用0赋值,且该过程是递归的。即若该对象的某个成员对象未定义默认构造函数,那么该成员对象的基本数据类型和指针类型的成员同样会被以0赋值。

    故用new的时候请加上()

    运算符delete用来删除由new建立的对象,释放指针所指向的内存空间。

    ——————————————————————

    关于new数组类型的对象:

    语法格式: new 类型名 [数组长度];

    delete[] 指针名;

    如int* p = new int[10]();

    delete[] p;

    ——————————————————————

    多维数组:

    语法格式: new 类型名T[第一维长度][第二维长度]...;

    其中第1维长度是任何结果为正整数的表达式,其余必须是正整数的常量表达式(因为是常量,故不能直接分配两维都不固定的数组)。

    若内存申请成功,返回指向新分配内存的首地址的指针,但不是T类型指针,而是指向T类型数组的指针,数组元素的个数为除第一维外各维下标表达式的乘积。

    如int (*p)[25][10];          //请把p抽出来看,p的类型为 int* [25][10]

       p = new int[10][25][10];

    则指针p即可以作为指针用,也可以当一个三维数组名用。

    再举例如下:

    int *p = new int[10];          //返回一个指向int的指针int*.
    
    int (*p)[10] = new int[2][10];    //new了一个二维数组,返回一个指向int[10]这种一维数组的指针int(*)[10].
    
    int (*p)[2][10] = new int[5][2][10]; //new了一个三维数组,返回一个指向二维数组int[2][10]这种类型的指针int (*)[2][10].

    注意:new int[0][10]和new int[][10]都是无分配内存。

    那么如果第二维都不确定怎么办呢?

        int **a = new int*[n];
        for(int i = 0; i < n; i++)
            a[i] = new int[n]();
    //分配n*n的数组,还可以a[i] = new int[i]();有点java的味道...
      for(int i = 0; i < n; i++)
        delete[] a[i];
      delete[] a;
    当char * a=new char[10]后,程序结束需要delete [] a请问为什么不需要写delete [10] a ,即计算机是怎么知道是数组大小的?
    参考以下链接:
    https://blog.csdn.net/hazir/article/details/21413833


    How do compilers use “over-allocation” to remember the number of elements in an allocated array?

    // Original code: Fred* p = new Fred[n];
    char* tmp = (char*) operator new[] (WORDSIZE + n * sizeof(Fred));
    Fred* p = (Fred*) (tmp + WORDSIZE);
    *(size_t*)tmp = n;
    size_t i;
    try {
      for (i = 0; i < n; ++i)
        new(p + i) Fred();           // Placement new
    }
    catch (...) {
      while (i-- != 0)
        (p + i)->~Fred();            // Explicit call to the destructor
      operator delete[] ((char*)p - WORDSIZE);
      throw;
    }
    // Original code: delete[] p;
    size_t n = * (size_t*) ((char*)p - WORDSIZE);
    while (n-- != 0)
      (p + n)->~Fred();
    operator delete[] ((char*)p - WORDSIZE);

    How do compilers use an “associative array” to remember the number of elements in an allocated array?

    // Original code: Fred* p = new Fred[n];
    Fred* p = (Fred*) operator new[] (n * sizeof(Fred));
    size_t i;
    try {
      for (i = 0; i < n; ++i)
        new(p + i) Fred();           // Placement new
    }
    catch (...) {
      while (i-- != 0)
        (p + i)->~Fred();            // Explicit call to the destructor
      operator delete[] (p);
      throw;
    }
    arrayLengthAssociation.insert(p, n);
    // Original code: delete[] p;
    size_t n = arrayLengthAssociation.lookup(p);
    while (n-- != 0)
      (p + n)->~Fred();
    operator delete[] (p);

    参考链接:https://isocpp.org/wiki/faq/compiler-dependencies#num-elems-in-new-array-overalloc

    malloc/free与new/delete的策略类似,new/delete是malloc/free的上层

    https://stackoverflow.com/questions/197675/how-does-delete-know-the-size-of-the-operand-array

    ====================================================================

    隐式空闲链表(任何操作的开销都与堆中已分配块和未分配块的总数呈线性关系)

    带边界标记的合并(块分配与堆块的总数呈线性关系,合并空闲块常数时间)

    显式空闲链表(分配时间从块总数减少为空闲块数量的线性时间,释放时间取决于空闲链表块的排序策略,LIFO则常数时间释放,按地址顺序排序则线性时间释放,如果采用了边界标记,合并时间常数)

    分离的空闲链表:简单分离存储 / 分离适配 / 伙伴系统

    诸神对凡人心生艳羡,厌倦天堂。
  • 相关阅读:
    vs code快捷键
    封装一个运动函数
    关于数组操作方式的总结
    学习html/css基础的重点笔记
    web新手——新闻列表这样写不容易出错
    AppCan——生成Web/微信App版,调用微信JSAPI支付方式,提示WeixinJSBridge内置对象undefined
    vue slot 占位符
    vue /deep/ css 不用1级1级找了
    vue 双向绑定 2个{{}}
    axios 请求接口 f12可以返回值 但是控制台打印报错
  • 原文地址:https://www.cnblogs.com/dirge/p/5351286.html
Copyright © 2020-2023  润新知