前言:C++中的智能指针有效解决了c++内存管理的问题。
1.背景(缘由)
在c++中,内存管理一直是对于程序员来讲的一个噩梦。通常存在以下3种情况,
1)忘记delete,造成内存泄露;
2)指针指向的内存被释放后(delete),造成指针成为野指针(悬挂指针)。这种情况若再次使用指针会造成未定义或非法内存的错误。
3)重复delete。
对于智能指针,可以有效解决上述的三个问题。
2.定义
智能指针是管理动态分配内存的类,借助引用计数技术,用于生存期控制,智能地在合适的时间完成析构的调用或动态内存的释放。
3.结构
在智能指针类中,包含原始指针和引用计数,以及对->和*运算符的重载。在实现引用计数中,可以使用辅助类和句柄类。以下是辅助类的定义,转自点击打开链接
<pre name="code" class="cpp">class U_Ptr
{
friend class HasPtr;
int *ip;
size_t use;
U_Ptr(int *p) : ip(p) , use(1)
{
cout << "U_ptr constructor called !" << endl;
}
~U_Ptr()
{
delete ip;
cout << "U_ptr distructor called !" << endl;
}
};
智能指针类,封装了U_Ptr类。
4.规则
1)每当创建智能指针时,将指针的引用计数初始化为1;
2)当对象赋值过程中,左边的对象引用计数减1,右边的对象引用计数加1;
3)当对象作为另一个对象副本创建时,复制指针并将相应引用计数加1。
4)当引用计数变为0时,调用析构函数或delete释放内存。
5.智能指针举例
由于 auto_ptr 基于【排他所有权模式】,这意味着:两个指针(同类型)不能指向同一个资源,复制或赋值都会改变资源的所有权。
新加入标准模板库(STL)的智能指针有两个:
shared_ptr:基于引用计数模型。每次有 shared_ptr 对象指向资源,引用计数器就加1;当有 shared_ptr 对象析构时,计数器减1;当计数器值为0时,被指向的资源将会被释放掉。且该类型的指针可复制和可赋值,即其可用于STL容器中。此外,shared_ptr 指针可与多态类型和不完全类型一起使用。主要缺点:无法检测出循环引用(后面会细说),如一颗树,其中既有指向孩子结点的指针又有指向父亲结点的指针,即孩子父亲相互引用。这会造成资源无法释放,从而导致内存泄露。为了 fix 这个问题,引入了另一个智能指针:weak_ptr.
weak_ptr:指向有shared_ptr 指向的资源(即其需要shared_ptr的参与,其辅助 shared_ptr 之用),但是不会导致计数。一旦计数器为0,不管此时指向资源的 weak_ptr 指针有多少,资源都会被释放,而所有的这些 weak_ptr 指针会被标记为无效状态(即 weak_ptr作为观察shared_ptr 的角色存在着,shared_ptr 不会感受到 weak_ptr 的存在)。