学习笔记--cpp内存管理(侯捷)

cpp memory

1. 基础知识

  • 使用memory的每一层面

    结构
  • new、delete、array new/delete、replacement new是运算符且不可被重载,而operator new/delete 是函数,可以被重载。

1.1 new

  • 用于动态创建一个对象。Person *p = new Person("name");

  • 编译器会将该运算符其转换为以下步骤。

    1. 通过operator new 获得一片内存的指针。
      • 实际上也是调用malloc。但保证不抛出异常。
    2. 将该指针强制转换成需要的指针Person *
    3. 通过指针调用该类的构造函数。
      • p->Person::Person("rui"),只有编译器才可以这样。

1.2 delete

  • 删除new创建的内存。

    code
    Person *p = new Person("name");
    ...
    delete p;
    
  • 编译器将其转换为以下步骤。

    1. 调用析构函数。p->~Person()
    2. operator delete该对象内存。
      • 实际上是调用free。但保证不抛出异常。

1.3 array new/delete

  • 创建或删除连续多个对象的内存。

    code
    Person *p = new Person[3];
    //必须要有默认构造方法
    //无法由参数给予初值
    delete [] p;  //若不用[]可能会导致内存泄漏
    
  • delete内存泄漏,实际上是因为只调用了一次析构函数,而其他对象的析构函数没有执行,最终导致泄漏。

    code
    int *pi = new int[3];
    ...
    //下面语句效果与 delete [] pi; 相同 但建议加上
    //因为int没有指向其他地方的内存,也没有析构函数,所以不会造成内存泄漏
    delete pi;
    

1.4 replacement new

  • 定位new运算符,允许将对象分配到已经分配的内存中。需要包含new头文件。

    • 等同于调用构造函数(编译器行为)。
    • 需要显式为每个对象调用析构函数(如果存在)
    • 应以创建顺序相反的顺序进行删除,(晚创建的对象可能依赖于早创建的对象)
    • 当所有对象都被销毁后才能释放存储这些对象的缓冲区。
    code
    //缓冲区
    char *buffer = new char[12];
    
    int *p1 = new (buffer) int;
    int *p2 = new (buffer+4) int;
    delete [] buffer;     //直接释放缓冲区,则会释放p1,p2指向的数据
    
    char *buffer2 = new char(sizeof(string)*2);
    Person *person1 = new(buffer2) Person("rui1");
    Person *person2 = new(buffer2+sizeof(Person)) Person("mm");
    //显式逆序调用析构函数,释放名字存放内存
    person2->~Person();
    person1->~Person();
    //最后释放缓冲区
    delete [] buffer2;
    

1.5 overload

2. memory allocator

内存分配器

3.malloc/free

posted @ 2021-10-13 21:34  Oniisan_Rui  阅读(419)  评论(0)    收藏  举报