Txing

欢迎来到 | 伽蓝之堂

0%

CPP Programming | Chapter 8:动态内存管理

Chapter 8 动态内存管理

动态内存基础

  • 栈内存 和 堆内存

    • 栈内存特点:更好的局部性,对象自动销毁

      • ```c++ int y = 2;
        1
        2
        3
        4
        5
        6
        7

        - 堆内存特点:运行期动态扩展,需要显式释放

        - ```c++
        int* y = new int(2);
        //......
        delete y;
  • 在c++中通常使用new和delete构造、销毁对象

  • 对象的构造分为两步:分配内存与在所分配的内存上构造对象;对象的销毁与之类似

  • new的几种形式

    • 构造单一对象/对象数组

    • nothrow new,int* y = new {std::nothrow} int[5]{};//内存分配失败不抛出异常,输出空指针

    • placement new,

      • ```c++ char ch[sizeof(int)]; int* y = new (ch) int(4);
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12

        - new auto,`int* y = new auto(3);`

        - new与对象对齐

        - delete 的常见用法

        - 销毁单一对象/对象数组

        - ```c++
        int* ptr = new int[5];
        delete[] ptr;
    • placement delete

  • 使用new与delete的注意事项

    • 根据分配的是单一对象还是数组,采用相应的方式销毁
    • delete nullptr
    • 不能delete一个非new返回的内存
    • 同一块内存不能delete多次
  • 调整系统自身的new/delete行为

    • 不要轻易使用

智能指针

  • 使用new与delete的问题:内存所有权不清晰,容易产生不销毁,多销毁的情况

  • C++的解决方案:智能指针

    • auto_ptr(c++17删除)
    • shared_ptr/uniuqe_ptr/weak_ptr
  • shared_ptr——基于引用计数的共享内存解决方案

    • 基本用法

      • ``` #include std::shared_ptr x(new int(3)); // 等价于 int* x = new int(3);
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20

        - reset() /get() 方法

        - get()返回T*

        - 指定内存回收逻辑

        - std::make_shared

        - 对对象数组的支持(C++17支持shared_ptr<T[]>;C++20支持make_shared分配数组)

        - 注意:shared_ptr管理的对象不要调用delete销毁

        - unique_ptr——独占内存的解决方案

        - 基本用法

        - ```c++
        std::unique_ptr<int> x(new int(3));
        std::unique_ptr<int> y = std::move(x); // y夺走x地址的所有权
    • unique_ptr 不支持复制,但可以移动

    • 为unique_ptr指定内存回收逻辑

      • ```c++ void fun(int* ptr) { std::cout << "fun is called"; delete ptr; } int main() { std::shared_ptr x(new int(3), fun); // 为x指定删除器fun,unique_ptr不能指定删除器 }
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15

        - weak_ptr——防止循环引入而引入的智能指针

        - 基于shared_ptr构造
        - lock() 方法

        ### 动态内存的相关问题

        - sizeof不会返回动态分配的内存大小

        - 使用分配器(allocator)来分配内存

        - ```c++
        std::allocator<int> al;
        int* ptr = al.allocate(3);//只分配内存,没有初始化
  • 使用malloc/free来管理内存

    • int *p1 = malloc(4*sizeof(int)); // 这三条语句分配内存等价
      int *p2 = malloc(sizeof(int[4]));
      int *p3 = malloc(4*sizeof *p3);
      
      free(p1);
      free(p2);
      free(p3);
  • 使用aligned_alloc来分配对齐内存

  • 动态内存与异常安全,避免异常后内存没有释放导致内存泄露

  • C++对于垃圾回收的支持