zoukankan      html  css  js  c++  java
  • C++内存分配方式——小结

    1 内存分配方式

    内存分配方式有如下三种:

    1. 从静态存储区域分配。内存在程序编译的时候就分配好了,这些内存在整个程序运行期间都存在,如全局变量、static变量等等。
    2. 在堆栈上分配。在函数执行期间,函数形参、函数内局部变量的存储单元都置于堆栈上,函数调用结束后自动从堆栈上释放。
    3. 从堆(heap)或自由存储空间分配,也叫动态内存分配。程序运行期间使用malloc()或new申请内存,使用free()或delete释放内存。

    一般的原则是:如果使用堆栈和静态存储就能够满足应用需求,就不要使用动态存储。因为,在堆上动态分配内存需要很多额外开销。

    2 常见的内存错误及其对策

    1. 内存分配未成功就使用了它——在使用内存之前检查指针是否为NULL。
    2. 内存分配虽然成功,但是尚未初始化就使用了它——建立初始化意识。
    3. 内存分配成功并且初始化,但是操作越过了内存的边界。
    4. 忘记释放内存或只释放了部分内存,造成内存泄漏。另外动态内存的申请和释放必须匹配。
    5. 释放了内存还在继续使用它。
      • 使用free()或者delete释放了内存之后,没有把指针设置为NULL,产生“野指针”。
      • 函数return返回指向堆栈内存的指针或引用,因为该函数结束时会自动销毁。
      • 多次释放同一块内存。

    3 指针参数传递内存

    如果函数的参数是一个指针,不要使用它去申请一块内存。因为编译器总是为函数的实参制作临时副本,指针p的副本_p值一样,因此指向同一块内存。但是如果使用_p来申请内存,p指向的内存则完全没有改变,反而在函数结束后造成内存的泄漏。

    4 free和delete与指针

    free()和delete只是把指针所指向的内存释放掉,并没有把指针本身删掉,大多数情况下p指向的地址仍不变,变成了“野指针”。

    • 指针消亡了不代表指针指向的内容消亡了。
    • 内存被释放了不代表指针消亡了或变成NULL。

    “野指针”有以下的成因

    • 没有初始化指针变量。
    • 指针被free()或者delete之后,没有置为NULL。
    • 指针超越了变量的作用范围

    5 malloc/free和new/delete

    malloc()与free()是C++/C语言的标准库函数,new/delete是C++的运算符,它们都可以动态申请和释放内存。

    对于非内部数据类型(如ADT/UDT)的对象而言,使用malloc()与free()无法满足要求:对象创建自动调用构造函数,对象销毁自动调用析构函数。由于malloc()与free()是库函数不是运算符,不在编译器控制权限之内,因此C++语言使用new/delete。

    6 malloc/free使用要点

    函数malloc原型如下:

    void *malloc(size_t size);

    例如申请一块长度为n的整型数组的内存:

    int *p = (int *)malloc(sizeof(int) * n);

    • malloc()函数返回值的类型是void *,所以在调用malloc要显式地进行类型转换。
    • malloc()只关心内存的总字数,不知道要申请的内存是什么类型,使用sizeof运算符计算类型的大小。

    函数free的原型如下:

    void free(void * memblock);

    7 new的3种使用方式

    new有3种使用方式:plain new、nothrow new、placement new。

    • plain new:普通的new,在失败后抛出标准异常std::bad_alloc——形式:new 
    • nothrow new:在失败后不抛出异常,而像过去一样检查返回值是否为NULL——形式:new(nothrow)
    • placement new:允许在一块已经分配成功的内存上重新构造对象或者数组——形式:new(p)

    8 new/delete使用要点

    new内置了sizeof、类型转换和类型安全检查功能,比使用malloc简单很多,例如。

    int *p = (int *)malloc(sizeof(int) * n);
    int *p = new int[n];
    
    Obj *o = new Obj;    //使用默认构造函数构造对象
    Obj *o = new Obj(1);    //使用初值1构造对象
    Obj *o = new Obj[100];    //如用new创建对象数组,只能使用默认构造函数
    
    delete p;  //释放一个对象
    delete []o;  //释放一个对象数组
    • 无论何种类型,new/delete和new[]/delete[]必须正确搭配使用
    • 多次delete一个不等于NULL的指针会导致运行时错误。

    (完)

  • 相关阅读:
    学会使用控件之comboxBox in asp.net 从简单开始(五)
    学会使用控件从简单开始(四)
    关于SQL计算差值的问题
    关于CSS3的一些代码
    显式实现的接口成员从简单开始(三)
    网页选项卡(TAB)今天晚上搞了一晚上这个
    关于页面刷新
    委托和匿名方法从简单开始(一)
    短信监听器
    android中handler处理message小例子
  • 原文地址:https://www.cnblogs.com/alwayswangzi/p/6505558.html
Copyright © 2011-2022 走看看