app的网站域名,网站建设方案案例,做电影网站如何赚钱,中华室内设计师网智能指针#xff1f;是一个指针吗#xff1f;这里给大家说的是#xff0c;它不是一个指针#xff0c;但它模拟了指针所具有的功能。那么#xff0c;为什么要有智能指针的引入呢#xff1f;看看下面的例子吧~ void FunTest()
{int *p new int[10];FILE *pFile fopen(是一个指针吗这里给大家说的是它不是一个指针但它模拟了指针所具有的功能。那么为什么要有智能指针的引入呢看看下面的例子吧~ void FunTest()
{int *p new int[10];FILE *pFile fopen(1.txt,r);if(pFile NULL){return;}if(p){delete[] p;p NULL;}
}
在c动态内存分配空间时是由用户自己维护的所以当new出来空间后必须由用户手动释放。再看看上面的这个代码有什么问题呢显然的当1.txt这个文件不存在时pFile就为空这就使后面释放p的语句没有执行导致内存泄漏。那么怎么解决这类问题呢 这就引入了我们重要的智能指针所谓智能指针就是智能化的管理动态开辟的资源的释放工作。
1、模拟实现auto_ptr templatetypename T
class AutoPtr
{
public:AutoPtr(T* p):_p(new T(1)){coutAutoPtr()endl;_p p;}AutoPtr(AutoPtr ap):_p(ap._p){coutAutoPtr(AutoPtr ap)endl;ap._p NULL;}AutoPtrT operator(AutoPtr ap){coutAutoPtrT operator(AutoPtr ap)endl;if(this ! ap){delete _p;_a ap._p;ap._p NULL;}}~AutoPtr(){cout~AutoPtr()endl;if (_p){delete _p;_p NULL;}}
public:T operator*(){return *_p;}T* operator-(){return _p;}
private:T *_p;
};void FunTest()
{AutoPtrint ap new int;AutoPtrint ap1(ap);*ap1 10;*(ap1.operator-()) 20;
}
int main()
{FunTest();return 0;
} 智能指针AutoPtr的特点是只可以管理一个对象看一下监视窗口 这样就会导致资源被转移。 当然AutoPtr还有另一种实现方式
templatetypename T
class AutoPtr
{
public:AutoPtr(T* p):_p(new T(1)){coutAutoPtr()endl;_p p;_owner true;}AutoPtr(AutoPtr ap):_p(ap._p){coutAutoPtr(AutoPtr ap)endl;ap._owner false;ap._p NULL;_owner true;}AutoPtrT operator(AutoPtr ap){coutAutoPtrT operator(AutoPtr ap)endl;if(this ! ap){delete _p;_a ap._p;ap._owner false;ap._p NULL;_owner true;}}~AutoPtr(){cout~AutoPtr()endl;if (_p){delete _p;_p NULL;_owner false;}}
public:T operator*(){return *_p;}T* operator-(){return _p;}
private:T *_p;bool _owner;
};void FunTest()
{AutoPtrint ap new int;AutoPtrint ap1(ap);*ap1 10;*(ap1.operator-()) 20;}int main()
{FunTest();return 0;
}这种方式就是定义一个私有成员用来标记当前对象的状态若为false表示当前对象已不再指向任何空间若为true说明该对象指向申请的那块内存。 那么这种类型的指针有什么弊端吗首先只能管理单个对象每次只有一个对象可使用申请的空间。其次使得资源转移另一个对象使用时前一个对象将赋为空。
但是切记不要使用auto_ptr。
2、模拟实现scoped_ptr
scoped_ptr与auto_ptr一样都是管理单个对象的。它的作用是在一个类中防止拷贝。说起防止拷贝大家会想到把它定义为私有的总可以了吧。其实并不可以因为访问私有成员或函数的方式还有将调用它的函数声明为类的友元就ok啦。所以在这里我们将学到一种防拷贝的方式只声明不定义且将拷贝构造和赋值运算符重载声明为私有即可。
实现如下
templatetypename T
class ScopedPtr
{
public:ScopedPtr(const T* p):_p(p){}~ScopedPtr(){if(_p){delete _p;_p NULL;}}T operator*(){return *_p;}T* operator-(){return _p;}
private:ScopedPtr(const ScopedPtr);ScopedPtrT operator(const ScopedPtr);
private:T* _p;
};void FunTest()
{ScopedPtrint sp new int;ScopedPtrint sp1(sp); //error,这样就使用不了拷贝构造函数了ScopedPtrint sp1 sp; //error使用不了赋值运算符重载}int main()
{FunTest();return 0;
} scoped_ptr实现的机制体现了它的独占性当一个对象占用一块空间时其他对象将无法使用。并且解决了不让资源转移的问题。
注在STL源码库中使用的是scoped_ptr而在boost库中使用的是unique_ptr。两个其实是一样的。 3、模拟实现shared_ptr
前面两个智能指针都是管理单个对象而这个shared_ptr则是可以管理多个对象。它们之间的资源是共享的。
以下代码是使用引用计数的方式实现资源共享。
实现代码如下 templatetypename T
class SharedPtr
{
public:SharedPtr(T* p NULL):_p(p),_pCount(new int(1)){coutSharedPtr(T* p NULL)endl;}SharedPtr(SharedPtr sp):_p(sp._p),_pCount(sp._pCount){coutSharedPtr(SharedPtr sp)endl;}SharedPtrT operator(const SharedPtr sp){coutSharedPtrT operator(const SharedPtr sp)endl;if(_p ! sp._p){if(_p NULL){_p sp._p;_pCount sp._pCount;}else if(_p (*_pCount 1)){delete _p;_p sp._p;_pCount sp._p;}else{--(*_pCount);_p sp._p;_pCount sp._pCount;}if(sp._p)(*_pCount);}return *this;}~SharedPtr(){cout~SharedPtr()endl;if(_p --(*_pCount) 0){delete _p;_p NULL;}}
public:T operator*(){return *_p;}T* operator-(){return _p;}int UseCount(){if(_pCount ! NULL)return *_pCount;return 0;}private:T *_p;int *_pCount;
};void FunTest()
{SharedPtrint sp new int(1);SharedPtrint sp1(sp);SharedPtrint sp2;sp sp1;sp2 sp1;coutsp.UseCount()endl;coutsp1.UseCount()endl;coutsp2.UseCount()endl;
}int main()
{FunTest();return 0;
}运行结果此版本虽然实现了共享但也存在着不少问题比如线程安全问题、循环引用问题定置删除器问题等。这几个问题我们下一篇再详细解说哦。 希望大家可以对博客提出宝贵意见欢迎来访哦。