第12章 动态内存

  • 生存期
    • 全局对象:程序启动时分配,程序结束时销毁
    • 局部对象:进入其定义所在的程序块时被创建,离开块时被销毁
    • static对象:第一次使用前被分配,程序结束时销毁
    • 动态分配的对象:只有当显式地被释放时,才会被销毁
  • 程序内存:
    • 静态内存:局部static对象,类static数据成员,定义在任何函数外的变量→使用前分配内存,程序结束时销毁;
      • 局部static对象:令局部变量的声明周期贯穿函数调用及之后的时间,在程序执行路径第一次经过对象定义语句时初始化,知道程序终止被销毁
    • 栈内存:定义在函数内的非static对象→仅在其定义的程序块运行时存在;
      • 分配在静态或者栈内存中的对象由编译器自动创建和销毁
    • 动态内存:动态分配,生存期由程序控制→显示创建,显示销毁。
  • 动态内存:
    • new创建,delete销毁→确保正确释放内存困难。
    • (c++11)智能指针:shared_ptr 允许多个指针指向同一对象,unique_ptr 不允许...., weak_ptr 伴随类?,弱引用?,指向shared_ptr指向的对象。→memory头文件中
  • 使用动态生存期的资源:
    • 程序不知道自己需要多少对象;
    • 程序不知道所需对象的准确类型;
    • 程序需要在多个对象间共享数据。

零、术语表

一、动态内存和智能指针

  1. shared_ptr类
  • 模板类→创建:shared_ptr p1; shared_ptr> p2;

  • 初始化:

    • 默认初始化→保存空指针;
    • 其他方式?(12.1.3)
  • 操作:
    shared_ptr和unique_ptr共有:shared_ptr sp;p;*p;p->mem;p.get()?; swap(p,q);p.swap(q)
    shared_ptr 独有:make_shared (args);shared_ptr p(q);p=q;p.unique();p.use _count()

  • make_shared函数

    • 最安全的分配和使用动态内存的方法,memory头文件;
    • 类似顺序容器的emplace成员,用其参数来构造给定类型的对象;
      eg. shared_ptr p1 = make_shared(42);
      shared_ptr p2 = make_shared(10,'9');
    • 不传递参数时→值初始化;
  • shared_ptr的工作原理:

    • 可认为每个shared_ptr都有一个关联的计数器(引用计数);
    • 一旦计数器变为0,会自动释放所管理的对象→通过析构函数销毁, - shared_ptr的析构函数 递减它指向对象的引用计数/计数为0时释放内存;
    • 计数器:
      • 拷贝→计数器递增;
      • 赋值p = q → p指向对象计数递减,q指向对象计数递增;
      • 返回p→ 需要向调用者传递一个p的拷贝,计数递增。
      • shared_ptr被销毁,例如一个局部的shared_ptr离开其作用域→计数器递减
    • 由于在最后一个shared_ptr销毁前内存都不会释放,所以需要保证shared_ptr在无用之后不再保留;
  • 回顾知识点:
    基于const的重载→通过区分成员函数是否是const对其重载,分别适用于常量版本和非常量版本的对象。
    initializer_list→6.2.6

  1. 直接管理内存
  • 使用new分配和初始化对象:new无法为分配的对象命名,而是返回一个指向该对象的指针:int *pi = new int;
  • 初始化:
    • 默认初始化→默认状况下使用,(内置类型或组合类型对象的值未定义,类类型用默认构造函数);
      • 定义变量时没有指定初值,则变量被默认初始化
      • 内置类型,定义于任何函数体之外被初始化为0,否则不被初始化,值是未定义的→建议初始化每一个内置类型的变量
    • 直接初始化→圆括号,int *pi = new int(1024), string *s = new string(10,'9');
    • 列表初始化 vector *p = new vector{0,1,2,3,4,5}
    • 值初始化:→int *p = new int();
      • 内置类型,初始值设为0
      • 其余类型,默认初始化
  • 可以用new分配const对象:const int *pci = new const int(1024)→该对象必须初始化。
  • 使用delete释放内存:接受一个指向想要释放对象的指针:delete p,p必须指向一个动态分配的对象或空指针!,动态分配的const对象不可被改变但可被销毁。
    • 执行两个动作:销毁给定指针指向的对象,释放对应的内存。
    • 指向动态对象的指针必需记得在不用时释放内存,eg,当一个指针离开其作用域,它指向的对象什么都不会发生,如果是一个指向动态对象的指针,那么内存将不被释放。
  • new,delete使用常见问题
    • 忘记delete内存;
    • 使用已经释放掉的对象;
    • 同一块内存释放两次;
  • 空悬指针:指向一块曾经保存数据对象,但现在已经无效的内存的指针,如:int *p = new int(43); auto q = p; delete p;→q现在是一个空悬指针。
  1. shared_ptr和new结合使用

  2. unique_ptr

  3. weak_ptr

你可能感兴趣的:(第12章 动态内存)