指针是一个变量,其值为另一个变量的地址,即内存位置的直接地址。指针就像是一个目录,其值就像页码,页码指向某一个的内容。 普通指针
C++没有自动回收内存的机制,每次new出来的动态内存必须手动delete。如果忘记delete,资源未被释放,将导致内存泄露。多个指针指向同一个对象时,有一个指针释放了,但是其他指针并不知道这个情况,若继续使用那个被释放的指针将出错。问题3:野指针 没有经过初始化就直接拿来用的指针,将出错。 智能指针智能指针是一个模板类,用来存储指针(指向动态分配对象的指针)。智能指针是通过基本类型(模板类)指针构造类的对象,指针本身就是一个自定义的对象。当此对象被销毁时,即调用此对象的析构函数,释放此指针。智能指针其实就是对普通指针的封装,封装成一个类。通过重载*和->两个运算符使得智能指针表现得就像普通指针一样。能够像指针一样(运算符重载,解引用,指向对象成员)。RAII思想(资源分配及初始化)(Resource Acquisition Is Initialization)- 析构函数中完成资源的清理,可以保证资源的正确初始化和释放
- 如果对象是用声明的方式在栈上创建局部对象,那么RAII机制就会正常工作,当离开作用域对象会自动销毁而调用析构函数释放资源。
auto_ptr auto_ptr事实上是一个类,在构造对象时获取对象的管理权,无需考虑释放动态内存开辟的空间,在析构函数中直接释放,不会出现内存泄漏的问题。缺陷: 1)一个指针变量指向的空间不能由两个auto_ptr管理,不然会析构两次,使程序崩溃。2)auto_ptr的拷贝构造,将源指针的管理权交给目标指针,会使得源指针悬空,解引用是会出现很多问题。 3)auto_ptr不能用来管理数组,析构函数中用的是delete。 unique_ptrunique_ptr解决了auto_ptr编译不报错的问题。unique_ptr是auto_ptr的继承者,对于同一块内存只能有一个持有者。 unique_ptr和auto_ptr唯一区别就是unique_ptr不允许赋值操作,也就是不能放在等号的右边,这一定程度避免了一些误操作导致指针所有权转移。unique_ptr的核心特点就如它的名字一样,它拥有对持有对象的唯一所有权,即两个unique_ptr不能同时指向同一个对象。nique_ptr所持有的对象只能通过转移语义将所有权转移到另外一个unique_ptr。- release()释放所管理指针的所有权,返回原生指针。但并不销毁原生指针。
- reset()释放并销毁原生指针。如果参数为一个新指针,将管理这个新指针
shared_ptrunique_ptr不能多个指针指向同一个资源,而shared_ptr可以。每次复制或者多一个共享内存资源的shared_ptr时,计数+1;当shared_ptr计数为0时,证明所有指向同一资源的shared_ptr都全部释放了。shared_ptr 需要维护的信息有两部分: 常规的创建一个 shared_ptr: 为了构建一个std::shared_ptr对象,却进行了两次内存分配,而且第二次内存分配分配的内存还比较小,这一方面会影响程序性能,另一方面还会大大增加内存碎片产生的可能性。 复制一个 shared_ptr : std::make_shared创建一个 shared_ptr: std::make_shared的精妙之处就在于,它将std::shared_ptr构造中的两次内存分配降低到了一次。这会对提供程序性能和降低内存碎片都有帮助。 shared_ptr本身拥有的方法主要包括: 循环引用问题: 但是,shared_ptr也有一个致命的缺点,就是会出现循环引用 Shared_ptr 会出现循环引用的情况:要释放sp1->_next, 就需要先释放sp1。这样一来,就陷入了一个无限的循环当中,谁都释放不掉。如何解决?
weak_ptr std::weak_ptr 要与 std::shared_ptr 一起使用。有时候我们只是想找个指向这块内存的指针,但我们不想把这块内存的生命周期与这个指针关联,这种情况下,弱引用指针就代表“我指向这东西,但这东西什么时候释放不关我事儿。weak_ptr是辅助shared_ptr的存在,它只提供对管理对象的访问手段,同时可以实时动态知道所指向的对象是否存活,起到观察者的作用。 weak_ptr不具有普通指针的行为,没有重载operator *和->,只能想像旁观者一样观测资源的使用情况。计数区域引进新的计数变量weak_count,来作为弱引用指针。weak_ptr的构造和析构不会引起shared_ptr的计数的增加和减少,只会引起weak_count的增加和减少。资源的释放只取决shared的计数,当计数为0时,释放资源,weak_ptr不控制资源的生命周期。计数区域的释放取决于shared计数和weak计数,当两者都为0时,才释放计数区域。weak_ptr本身拥有的方法主要包括: 循环引用问题的解决: 要释放sp1->_next, 就需要先释放sp1,已经释放,所以sp1->_next释放。要释放sp2->_prev,就需要先释放sp2,已经释放,所以sp2->_prev释放。总结 unique_ptr:内存的所有者或者说管理者必须是唯一的。如果进入不同的模块或者调用者,那么执行所有权转移。 shared_ptr: 内存由多个指针变量共同使用,共同拥有内存的所有权。但是必须杜绝循环拷贝! weak_ptr: 对内存的使用仅仅是访问而已,不涉及其生命周期的管理。 ——————
|