内存管理和智能指针

内存管理和智能指针,第1张

内存管理和智能指针

目录
  • C++中五大存储区
  • 静态内存和动态内存
    • 静态内存和栈内存
    • 动态内存和智能指针
    • 直接管理内存
    • 智能指针类
      • shared_ptr的使用
      • shared_ptr与make_shared函数
      • make_shared函数与auto

C++中五大存储区
  1. 栈:保存局部变量和函数的参数。栈上的内容只在函数范围内存在,当函数运行结束的时候,这些内容也会自动销毁。其特点是效率高但是空间大小有限。向低地址生长。
  2. 堆:由程序员自己创建并维护,通过malloc系列函数或者new *** 作符分配的内存。其生命周期由free和delete决定。在没有释放之前一直存在,直到程序结束。其特点是使用灵活,空间比较大,但容易出错。
  3. 全局/静态存储区:存储程序的静态(static)变量以及全局变量,整个程序的生命周期都存在的。
  4. 常量存储区:这是一块比较特殊的存储区,他们里面存放的是常量,不允许修改。
  5. 代码区:存放函数体的二进制代码。
静态内存和动态内存 静态内存和栈内存
  1. 所谓静态内存是用来保存一个程序中局部 static 对象、类 static 对象以及定义在任何函数之外的变量。 而栈内存是用来保存定义在函数内的非 static 对象。
  2. 分配在静态或栈内存中的对象由编译器自动创建和销毁。
  3. 除了静态内存和栈内存之外,每个程序还拥有一个内存池。这部分内存被称作自由空间或堆。
  4. 程序用堆来存储动态分配的对象-即那些在程序运行时分配的对象。动态对象的生命周期由程序来控制,也就是说,当动态对象不再使用的时候,必须由我们自己编写的代码显式地销毁它们。
动态内存和智能指针
  1. 除了自动对象和 static 对象外,C++ 还支持动态分配对象。 动态分配的对象的生存期与它们在哪里创建是无关的,只有当显式地被释放时,这些对象才会销毁。

  2. 动态对象的正确释放也是我们编程中极其容易出错的地方。

  3. 为了更安全地使用动态内存,标准库定义了两个智能指针类型来管理动态分配的对象 ,当一个对象被释放时,指向它的智能指针可以确保自动地释放它。

  4. 一般来说,我们在程序中,使用动态内存的三个原因:

    程序不清楚使用对象数量;
    不清楚对象类型;
    要在多个对象之间共享数据。

直接管理内存
  1. 使用new和delete直接管理动态内存,包含此 *** 作的类不能使用默认的析构函数和赋值拷贝。

  2. new动态分配的对象是默认初始化的,类类型调用默认构造函数。也可以使用直接初始化、列表初始化和值初始化。

  3. 类类型的值初始化调用默认构造函数,内置类型值初始化为一个类似0的初值而非未定义。

  4. 动态分配const对象必须初始化。

  5. 为了防止内存耗尽抛出异常,可以为new输入参数nothrow,叫做定位new。

  6. delete只能释放使用new分配的对象,而且不能重复释放。

  7. 内置指针动态分配的对象在显示删除之前一直存在。

智能指针类

智能指针的行为类似常规指针,重要的区别是它负责自动的释放所指向的对象。

  1. shared_ptr:允许多个指针指向同一个对象,shared_ptr 调用类的析构函数销毁对象并且释放对象关联的内存。保证有共享指针指向的对象一直存在,因此需要保证删除不需要的共享指针。特别是在容器中。
  2. unique_ptr:“独占”所指向的对象。
  3. weak_ptr:一种弱引用,指向 shared_ptr 所管理的对象。

类似vector,智能指针也是模板。因此,当创建一个智能指针时,必须提供额外的信息,指针指向的类型。

shared_ptr的使用

与vector一样,在尖括号内给出类型,之后是所定义的这种智能指针的名字:

shared_ptr p1; //定义一个shared_ptr智能指针p1,指向string
shared_ptr> p2; //定义一个shared_ptr智能指针p2,指向类型是int的list
shared_ptr与make_shared函数

最安全的分配和使用动态内存的方法就是调用一个名为make_shared的标准库函数,此函数在动态内存中分配一个对象并初始化它,返回指向此对象的shared_ptr。头文件和share_ptr相同,make_shared的头文件也定义在memory中。
当要使用make_shared时,必须指定想要创建对象的类型,定义格式与模板类相同。在函数名之后跟一个尖括号,在其中给出类型:

//指向一个值为42的int的shared_ptr
shared_ptr p3 = make_shared(42);
//指向一个值为"9999999999"的string的shared_ptr
shared_ptr p4 = make_shared(10,'9');
//指向一个值初始化为0的int的shared_ptr
shared_ptr p5 = make_shared();
make_shared函数与auto

我们可以认为每个shared_ptr都有一个关联的计数器,通常称其为引用计数,无论何时我们拷贝一个shared_ptr,计数器都会递增。当我们给shared_ptr赋予一个新值或是shared_ptr被销毁(例如一个局部的shared_ptr离开其作用域)时,计数器就会递减,一旦一个shared_ptr的计数器变为0,它就会自动释放自己所管理的对象。

auto r = make_shared(42);//r指向的int只有一个引用者
r=q;//给r赋值,令它指向另一个地址
	//递增q指向的对象的引用计数
	//递减r原来指向的对象的引用计数
	//r原来指向的对象已没有引用者,会自动释放

——————
2021.11.24
软件园

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5593602.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-15
下一篇 2022-12-15

发表评论

登录后才能评论

评论列表(0条)

保存