智能指针概念和使用
目录结构:
一 通过案例引入智能指针
二 智能指针的作用
三 设计辅助类实现智能指针作用
四 设计类模板实现智能指针作用
五 使用stl和boost提供的标准智能指针类模板处理问题
一 通过案例引入智能指针
有如下的程序:
#include <iostream>
using namespace std;
class exam
{
public:
exam(int *p):ptr(p){}
exam(exam &obj)
{
ptr = obj.ptr;
}
~exam()
{
delete ptr;
}
private:
int *ptr;
};
int main()
{
exam obj1(new int(4));
exam obj2(obj1);
exam obj3(new int(10));
obj3 = obj2;
return 0;
}
程序中存在两个问题:
1 程序运行出现段错误,double free错误
2 同时也造成了内存泄露
为了较为方便解决类似上面的问题,引入了智能指针的概念
二 智能指针概念和作用
以下关于智能指针说法来之网络,大家可以动手自己搜索进一步查找概念
1 动态内存管理经常会出现两种问题:
一种是忘记释放内存,会造成内存泄漏;一种是尚有指针引用内存的情况下就释放了它,就会产生引用非法内存的指针
2 智能指针(smart pointer)的一种通用实现技术是使用引用计数(reference count)。
智能指针类将一个计数器与类指向的对象相关联,引用计数跟踪该类有多少个对象的指针指向同一对象
3 智能指针就是一个类,当超出了类的作用域是,类会自动调用析构函数,析构函数会自动释放资源
4 编程中出现问题:
第一是创建new之后,忘记了delete;
第二是,多个指针指向一个new的空间,但是其中的一个delete之后,剩下的依然去访问。
然后出现访问一个空指针的情况
5 智能指针(smart pointer)的一种通用实现技术是使用引用计数(reference count)。
智能指针类将一个计数器与类指向的对象相关联,引用计数跟踪该类有多少个对象共享同一指针。
以上的概念 作用或者实现叙述比较抽象,通过以下的代码进一步理解作用
三 设计辅助类实现智能指针作用
编程思想如下:
1 每次创建类的新对象时,初始化指针并将引用计数置为1;
2 当对象作为另一对象的副本而创建时,
拷贝构造函数拷贝指针并增加与之相应的引用计数;
3 对一个对象进行赋值时,
赋值操作符减少左操作数所指对象的引用计数(如果引用计数为减至0,则删除对象),并增加右操作数所指对象的引用计数;
4 调用析构函数时,构造函数减少引用计数(如果引用计数减至0,则删除基础对象)
#include <iostream>
using namespace std;
class point
{
friend class exam;
point(int *pr):pin(pr),count(1){}
~point()
{
delete pin;
}
int *pin;
int count;
};
class exam
{
public:
exam(int *p):ptr(new point(p)){}
exam(exam &obj)
{
ptr = obj.ptr;
ptr->count++;
}
exam &operator=(const exam &obj)
{
if(--ptr->count == 0)
delete ptr;
ptr = obj.ptr;
ptr->count++;
}
~exam()
{
if(--ptr->count == 0)
delete ptr;
}
private:
point *ptr;
};
int main()
{
exam obj1(new int(4));
exam obj2(obj1);
exam obj3(obj2);
exam obj4(new int(8));
obj4 = obj3;
return 0;
}
解决了引例中的两个问题
四 设计类模板实现智能指针作用
以上实现存在以下缺点:
是每个含有指针的类的实现代码中都要自己控制引用计数,比较繁琐。
特别是当有多个这类指针时,维护引用计数比较困难
重新设计封装指针的类,
为了避免上面方案中每个使用指针的类自己去控制引用计数,可以用一个类把指针封装起来。封装好后,这个类对象可以出现在用户类使用指针的任何地方,表现为一个指针的行为。我们可以像指针一样使用它,而不用担心普通成员指针所带来的问题,我们把这样的类叫句柄类
模板类,可以封装各种类型的指针
#include <iostream>
using namespace std;
class stub
{
public:
void print()
{
cout<<"stu:print"<<endl;
}
~stub()
{
cout<<"stub:destructor"<<endl;
}
};
template<typename T>
class smartptr
{
public:
smartptr(T *p = NULL):ptr(p),pUse(new size_t(1)){}
smartptr(const smartptr &src):ptr(src.ptr),pUse(src.pUse)
{
++*pUse;
}
smartptr &operator=(const smartptr &rhs)
{
++*rhs.pUse;
decrUse();
ptr = rhs.ptr;
pUse = rhs.pUse;
return *this;
}
T *operator->()
{
if(ptr)
return ptr;
}
const T *operator->() const
{
if(ptr)
return ptr;
}
T &operator*()
{
if(ptr)
return *ptr;
}
const T &operator*()const
{
if(ptr)
return *ptr;
}
~smartptr()
{
decrUse();
}
private:
void decrUse()
{
if(--*pUse == 0)
{
delete ptr;
delete pUse;
}
}
T *ptr;
size_t *pUse;
};
int main()
{
/*
smartptr<stub> t1(new stub);
smartptr<stub> t2(t1);
smartptr<stub> t3(new stub);
t3 = t2;
t1->print();
(*t3).print();*/
smartptr<string> t1(new string("mike"));
smartptr<string> t2;
cout<<*t1<<endl;
cout<<t1->length()<<endl;
t2 = t1;
cout<<*t2<<endl;
cout<<*t1<<endl;
return 0;
}
五 使用stl和boost提供的标准智能指针类模板处理问题
库的开发者:开发标准的实现智能指针的类模板
用库中提供的智能指针模板类解决项目中的问题
1 使用stl提供的auto_ptr智能指针模板类:处理string *的情况
#include <iostream>
#include <memory>
using namespace std;
int main()
{
auto_ptr<string> obj(new string("mike"));
auto_ptr<string> obj1;
cout<<*obj<<endl;
cout<<obj->length()<<endl;
obj1 = obj;
cout<<*obj1<<endl;
cout<<*obj<<endl;
return 0;
}
2 使用boost库中提供shared_ptr智能指针模板类处理string *的案例:
#include <iostream>
#include <memory>
#include <boost/smart_ptr.hpp>
using namespace std;
int main()
{
boost::shared_ptr<string> obj(new string("mike"));
boost::shared_ptr<string> obj1;
cout<<*obj<<endl;
cout<<obj->length()<<endl;
obj1 = obj;
cout<<*obj1<<endl;
cout<<*obj<<endl;
return 0;
}