第十二章 动态内存

来源:互联网 发布:网络大电影的宣发 编辑:程序博客网 时间:2024/04/30 07:21
  1. 静态内存用来保存局部 static 对象、类 static 数据成员以及定义在任何函数之外的变量。栈内存用来保存定义在函数内的非 static 对象。分配在静态或栈内存中的对象由编译器自动创建和销毁。除了静态内存和栈内存,每个程序还拥有一个内存池。这部分内存被称作自由空间(free store)或堆(heap)。程序用堆来存储动态分配的对象,即那些在程序运行时分配的对象。动态对象的生存期由程序来控制,也就是说,当动态对象不再使用时,我们的代码必须显示地销毁它们。
  2. 最安全的分配和使用动态内存的方法是调用一个名为 make_shared 的标准库函数。
  3. 当指向一个对象的最后一个 shared_ptr 被销毁时, shared_ptr 类会自动销毁此对象。它是通过折构函数完成销毁工作的。
  4. 如果你将 shared_ptr 存放在一个容器中,而后不再需要全部元素,而只使用其中一部分,要记得用 erase 删除不再需要的那些元素。
  5. 使用动态内存的一个常见原因是允许多个对象共享相同的状态。
  6. 默认情况下,动态分配的对象是默认初始化的。
  7. 处于与变量初始化相同的原因,对动态分配的对象进行初始化通常是个好主意。
  8. 用 delete 释放一块非 new 分配的内存,或是将相同的指针值释放多次,其行为是未定义的。
  9. 与 new 类似, delete 表达式也执行两个动作:销毁给定的指针指向的对象;释放对应的内存。释放一个空指针总是没错的,不管是不是指向动态分配的内存。
  10. 不能进行内置指针到智能指针的隐式转换。
  11. 当将一个 shared_ptr 绑定到一个普通指针时,我们就将内存的管理责任交给了这个 shared_ptr 。一旦这样做了,我们就不应该再使用内置指针来访问 shared_ptr 所指向的内存了。
  12. 智能指针类型定义了一个名为 get 的函数,它返回一个内置指针,指向智能指针管理的对象。 get 用来将指针的访问权限传给代码,你只有在确定代码不会 delete 指针的情况下,才能使用 get 。特别是,永远不要用 get 初始化另一个智能指针或者为另一个智能指针赋值。
  13. 如果使用智能指针,即使程序块过早结束,智能指针类也能确保在内存不再需要时将其释放;如果使用内置指针管理内存,且在 new 之后在对应的 delete 之前发生异常,则内存不会被释放。
  14. 为了正确使用智能指针,我们必须坚持一些基本规范:
        ① 不适用相同的内置指针值初始化(或 reset )多个智能指针。
        ② 不 delete get() 返回的指针。
        ③ 不适用 get() 初始化或 reset 另一个智能指针。
        ④ 如果你使用 get() 返回的指针,记住当最后一个对应的智能指针销毁后,你的指针就变为无效了。
        ⑤ 如果你使用智能指针管理的资源不是 new 分配的内存,记住传递给它一个删除器。
  15. unique_ptr 不支持普通的拷贝或赋值操作。但是我们可以拷贝或赋值一个将要被销毁的 unique_ptr 。
  16. unique_ptr 的 release() 函数不会释放对象内存。
  17. 由于对象可能不存在,我们不能使用 weak_ptr 直接访问对象,而必须调用 lock 。
  18. 标准库中包含一个名为 allocator 的类,允许我们将分配和初始化分离。使用 allocator 通常会提供更好的性能和更灵活的内存管理能力。大多数英勇应该使用标准库容器而不是动态分配的数组。使用容器更为简单而且更不容易出现内存管理错误并且可能有更好的性能。
  19. 要记住我们所说的动态数组并不是数组类型,由于分配的内存并不是一个数组类型,因此不能对动态数组调用 begin 或 end 。出于相同的原因,也不能用范围 for 语句来处理动态数组中的元素。
  20. delete [] pa; 该语句销毁 pa 指向的数组中的元素,并释放对应内存。数组中的元素按逆序销毁,即,最后一个元素首先被销毁,然后是倒数第二个,依此类推。即使使用类型别名定义动态数组, delete 时[]也不能省略。
  21. new 将内存分配和对象构造组合在了一起。 delete 将对象折构和内存释放组合在了一起。
  22. 现代 C++ 程序应尽可能使用智能指针。
0 0