电信网站备案查询,高端网站设计工作室,推盟,西安网站开发公司定制为什么需要智能指针#xff1f; 解决忘记释放内存导致内存泄漏的问题。解决异常安全问题。 #includeiostream
using namespace std;int div()
{int a, b;cin a b;if (b 0)throw invalid_argument(除0错误);return a / b;
}
void Func(…为什么需要智能指针 解决忘记释放内存导致内存泄漏的问题。解决异常安全问题。 #includeiostream
using namespace std;int div()
{int a, b;cin a b;if (b 0)throw invalid_argument(除0错误);return a / b;
}
void Func()
{// 1、如果p1这里new 抛异常会如何// 2、如果p2这里new 抛异常会如何// 3、如果div调用这里又会抛异常会如何int* p1 new int;int* p2 new int;cout div() endl;delete p1;delete p2;
}
int main()
{try{Func();}catch (exception e){cout e.what() endl;}return 0;
}问如果p1这里new 抛异常会如何 答p1、p2不会开空间内存没有释放 问如果p2这里new 抛异常会如何 答p2不会开空间内存没有得到释放 问如果div调用这里又会抛异常会如何 答内存没有被释放。 那么如何解决呢 可以利用智能指针来解决这个问题。 智能指针的使用及其原理
RAII RAIIResource Acquisition Is Initialization是一种利用对象生命周期来控制程序资源如内 存、文件句柄、网络连接、互斥量等等的简单技术。 在对象构造时获取资源接着控制对资源的访问使之在对象的生命周期内始终保持有效最后在 对象析构的时候释放资源。借此我们实际上把管理一份资源的责任托管给了一个对象。这种做 法有两大好处 不需要显示地释放资源。采用这种方式对象所需的资源在其生命期内始终保持有效。 我们用一个类来封装一下这个指针实现如下 #includeiostream
using namespace std;namespace hayaizo
{templateclass Tclass smart_ptr{public:smart_ptr(T* ptr nullptr):_ptr(ptr){}~smart_ptr(){if (_ptr){cout delete: _ptr endl;delete _ptr;}}private:T* _ptr;};
}int div()
{int a, b;cin a b;if (b 0)throw invalid_argument(除0错误);return a / b;
}
void Func()
{hayaizo::smart_ptrint sp1(new int);hayaizo::smart_ptrint sp2(new int);cout div() endl;
}int main(void)
{try {Func();}catch (const exception e){cout e.what() endl;}return 0;
}运行结果 既然是指针那么也需要支持解引用*和-重载这两个符号就好了。 namespace hayaizo
{templateclass Tclass smart_ptr{public:smart_ptr(T* ptr nullptr):_ptr(ptr){}~smart_ptr(){if (_ptr){cout delete: _ptr endl;delete _ptr;}}T operator*(){return *_ptr;}T* operator-(){return _ptr;}private:T* _ptr;};
}但这样地封装会有一个致命的缺点一个地址只能被一个智能指针指向不然会导致同一块内存释放两次的问题我们看看官方库中的auto_ptr是怎么解决的。 可以看到sp1的地址变成了sp2的地址了然后sp1的地址变成了nullptr。 手搓一个低配版的auto_ptr namespace hayaizo
{templateclass Tclass auto_ptr{public:auto_ptr(T* ptr nullptr):_ptr(ptr){}auto_ptr(auto_ptrTap):_ptr(ap._ptr){ap._ptr nullptr;}auto_ptrT operator(auto_ptrT ap){if (this ! ap){if (_ptr){delete _ptr;}_ptr ap._ptr;ap._ptr nullptr;}return *this;}~auto_ptr(){if (_ptr){cout delete: _ptr endl;delete _ptr;}}T operator*(){return *_ptr;}T* operator-(){return _ptr;}private:T* _ptr;};
}但这样确实可以解决问题但是已经失去了原生指针的功能了原生指针是支持同一个地址被很多个指针指向的在介绍解决方法之前得先介绍unique_ptr。 unique_ptr unique_ptr非常粗暴直接不让你拷贝把拷贝构造禁掉了。 templateclass Tclass unique_ptr{public:unique_ptr(T* ptr nullptr):_ptr(ptr){}unique_ptr(unique_ptrT ap)delete{}unique_ptrT operator(unique_ptrT ap)delete{}~unique_ptr(){if (_ptr){cout delete: _ptr endl;delete _ptr;}}T operator*(){return *_ptr;}T* operator-(){return _ptr;}private:T* _ptr;};shared_ptr shared_ptr的原理是通过引用计数的方式来实现多个shared_ptr对象之间共享资源。 shared_ptr在其内部给每个资源都维护了着一份计数用来记录该份资源被几个对象共 享。在对象被销毁时(也就是析构函数调用)就说明自己不使用该资源了对象的引用计数减 一。如果引用计数是0就说明自己是最后一个使用该资源的对象必须释放该资源。如果不是0就说明除了自己还有其他对象在使用该份资源不能释放该资源否则其他对 象就成野指针了。 比如我用三个智能指针指向地址0x00112233因此计数为3当计数等于0的时候再进行销毁。 那么这里的计数可以单纯用一个int _cnt或者static int _cnt来表示吗 答案是否定的。 如果是int _cnt那么每个对象都是单独的计数。 如果是static int _cnt那么每个对象都是用的同一份计数。 所以这里需要用一个指针来表示计数。 templateclass Tclass shared_ptr{public:shared_ptr(T* ptr nullptr):_ptr(ptr),_cnt(new int(1)){}shared_ptr(shared_ptrT ap):_ptr(ap._ptr),_cnt(ap._cnt){}void Release(){if (--(*_cnt) 0){cout delete: _ptr endl;delete _ptr;}}shared_ptrT operator(const shared_ptrT sp){//p1p1的情况if (_ptr sp._ptr){return *this;}Release();_ptr sp._ptr;_cnt sp._cnt;(*_cnt);return *this;}int use_count(){return *_cnt;}T* get() const{return _ptr;}T operator*(){return *_ptr;}T* operator-(){return _ptr;}~shared_ptr(){Release();}private:T* _ptr;int* _cnt;};}循环引用 这里的n1和n2的引用计数都是2所以形成了相互制约的局面。 n1的销毁看n2n2的销毁看n1。 weak_ptr weak_ptr是为配合shared_ptr而引入的一种智能指针。 weak_ptr可以从一个shared_ptr或另一个weak_ptr对象构造它的构造和析构不会引起shared_ptr引用记数的增加或减少 templateclass Tclass weak_ptr{public:weak_ptr():_ptr(nullptr){}weak_ptr(const shared_ptrT sp):_ptr(sp.get()){}weak_ptrT operator(const shared_ptrT sp){_ptr sp.get();return *this;}T operator*(){return *_ptr;}T* operator-(){return _ptr;}private:T* _ptr;};struct Node
{int _val;hayaizo::weak_ptrNode _next;hayaizo::weak_ptrNode _prev;~Node(){cout ~Node endl;}
};int main(void)
{hayaizo::shared_ptrNode n1(new Node);hayaizo::shared_ptrNode n2(new Node);n1-_next n2;n2-_prev n1;return 0;
}很简单就是n1内部的指针不参与引用计数用另外的类封装起来就好了就不会动shared_ptrT里面的引用计数了。 定制删除器 其实就是个仿函数可以自己传删除方案。 //默认删除器templateclass Tstruct Delete{void operator()(T* ptr){cout delete: ptr endl;delete ptr;}};templateclass T,class DDeleteTclass shared_ptr{public:shared_ptr(T* ptr nullptr):_ptr(ptr),_cnt(new int(1)){}shared_ptr(shared_ptrT ap):_ptr(ap._ptr),_cnt(ap._cnt){}void Release(){if (--(*_cnt) 0){cout delete: _ptr endl;D del;del(_ptr);//D()(_ptr);匿名对象调用()}}shared_ptrT operator(const shared_ptrT sp){//p1p1的情况if (_ptr sp._ptr){return *this;}Release();_ptr sp._ptr;_cnt sp._cnt;(*_cnt);return *this;}int use_count(){return *_cnt;}T* get() const{return _ptr;}T operator*(){return *_ptr;}T* operator-(){return _ptr;}~shared_ptr(){Release();}private:T* _ptr;int* _cnt;};templateclass T
struct DeleteArray
{void operator()(T* ptr){cout delete[] ptr endl;delete[] ptr;}
};templateclass T
struct Free
{void operator()(T* ptr){cout free ptr endl;free(ptr);}
}; 总代码
//#includeiostream
//using namespace std;
//
//int div()
//{
// int a, b;
// cin a b;
// if (b 0)
// throw invalid_argument(除0错误);
// return a / b;
//}
//void Func()
//{
// // 1、如果p1这里new 抛异常会如何
// // 2、如果p2这里new 抛异常会如何
// // 3、如果div调用这里又会抛异常会如何
// int* p1 new int;
// int* p2 new int;
// cout div() endl;
// delete p1;
// delete p2;
//}
//int main()
//{
// try
// {
// Func();
// }
// catch (exception e)
// {
// cout e.what() endl;
// }
// return 0;
//}#includeiostream
using namespace std;namespace hayaizo
{templateclass Tclass auto_ptr{public:auto_ptr(T* ptr nullptr):_ptr(ptr){}auto_ptr(auto_ptrTap):_ptr(ap._ptr){ap._ptr nullptr;}auto_ptrT operator(auto_ptrT ap){if (this ! ap){if (_ptr){delete _ptr;}_ptr ap._ptr;ap._ptr nullptr;}return *this;}~auto_ptr(){if (_ptr){cout delete: _ptr endl;delete _ptr;}}T operator*(){return *_ptr;}T* operator-(){return _ptr;}private:T* _ptr;};templateclass Tclass unique_ptr{public:unique_ptr(T* ptr nullptr):_ptr(ptr){}unique_ptr(unique_ptrT ap)delete{}unique_ptrT operator(unique_ptrT ap)delete{}~unique_ptr(){if (_ptr){cout delete: _ptr endl;delete _ptr;}}T operator*(){return *_ptr;}T* operator-(){return _ptr;}private:T* _ptr;};//默认删除器templateclass Tstruct Delete{void operator()(T* ptr){cout delete: ptr endl;delete ptr;}};templateclass T,class DDeleteTclass shared_ptr{public:shared_ptr(T* ptr nullptr):_ptr(ptr),_cnt(new int(1)){}shared_ptr(shared_ptrT ap):_ptr(ap._ptr),_cnt(ap._cnt){}void Release(){if (--(*_cnt) 0){cout delete: _ptr endl;D del;del(_ptr);//D()(_ptr);匿名对象调用()}}shared_ptrT operator(const shared_ptrT sp){//p1p1的情况if (_ptr sp._ptr){return *this;}Release();_ptr sp._ptr;_cnt sp._cnt;(*_cnt);return *this;}int use_count(){return *_cnt;}T* get() const{return _ptr;}T operator*(){return *_ptr;}T* operator-(){return _ptr;}~shared_ptr(){Release();}private:T* _ptr;int* _cnt;};templateclass Tclass weak_ptr{public:weak_ptr():_ptr(nullptr){}weak_ptr(const shared_ptrT sp):_ptr(sp.get()){}weak_ptrT operator(const shared_ptrT sp){_ptr sp.get();return *this;}T operator*(){return *_ptr;}T* operator-(){return _ptr;}private:T* _ptr;};}struct Node
{int _val;hayaizo::weak_ptrNode _next;hayaizo::weak_ptrNode _prev;~Node(){cout ~Node endl;}
};templateclass T
struct DeleteArray
{void operator()(T* ptr){cout delete[] ptr endl;delete[] ptr;}
};templateclass T
struct Free
{void operator()(T* ptr){cout free ptr endl;free(ptr);}
}; int main(void)
{/*hayaizo::shared_ptrNode n1(new Node);hayaizo::shared_ptrNode n2(new Node);n1-_next n2;n2-_prev n1;*/hayaizo::shared_ptrNode, DeleteArrayNode n1(new Node[5]);hayaizo::shared_ptrNode n2(new Node);hayaizo::shared_ptrint, DeleteArrayint n3(new int[5]);hayaizo::shared_ptrint, Freeint n4((int*)malloc(sizeof(int)));return 0;
}
文章转载自: http://www.morning.qbtj.cn.gov.cn.qbtj.cn http://www.morning.ydzly.cn.gov.cn.ydzly.cn http://www.morning.ltkms.cn.gov.cn.ltkms.cn http://www.morning.zyrcf.cn.gov.cn.zyrcf.cn http://www.morning.rxydr.cn.gov.cn.rxydr.cn http://www.morning.tfrmx.cn.gov.cn.tfrmx.cn http://www.morning.wcjk.cn.gov.cn.wcjk.cn http://www.morning.jcjgh.cn.gov.cn.jcjgh.cn http://www.morning.wtrjq.cn.gov.cn.wtrjq.cn http://www.morning.xdjsx.cn.gov.cn.xdjsx.cn http://www.morning.cbynh.cn.gov.cn.cbynh.cn http://www.morning.yhwxn.cn.gov.cn.yhwxn.cn http://www.morning.sdktr.com.gov.cn.sdktr.com http://www.morning.txmlg.cn.gov.cn.txmlg.cn http://www.morning.xnflx.cn.gov.cn.xnflx.cn http://www.morning.sqlh.cn.gov.cn.sqlh.cn http://www.morning.rchsr.cn.gov.cn.rchsr.cn http://www.morning.ngmjn.cn.gov.cn.ngmjn.cn http://www.morning.neletea.com.gov.cn.neletea.com http://www.morning.cltrx.cn.gov.cn.cltrx.cn http://www.morning.qsswb.cn.gov.cn.qsswb.cn http://www.morning.aowuu.com.gov.cn.aowuu.com http://www.morning.wgqtt.cn.gov.cn.wgqtt.cn http://www.morning.jwgnn.cn.gov.cn.jwgnn.cn http://www.morning.dnmzl.cn.gov.cn.dnmzl.cn http://www.morning.qsswb.cn.gov.cn.qsswb.cn http://www.morning.vaqmq.cn.gov.cn.vaqmq.cn http://www.morning.jlpdc.cn.gov.cn.jlpdc.cn http://www.morning.ydwnc.cn.gov.cn.ydwnc.cn http://www.morning.nkjpl.cn.gov.cn.nkjpl.cn http://www.morning.kkdbz.cn.gov.cn.kkdbz.cn http://www.morning.hrdx.cn.gov.cn.hrdx.cn http://www.morning.nlrp.cn.gov.cn.nlrp.cn http://www.morning.wslpk.cn.gov.cn.wslpk.cn http://www.morning.nlwrg.cn.gov.cn.nlwrg.cn http://www.morning.sjli222.cn.gov.cn.sjli222.cn http://www.morning.xjkr.cn.gov.cn.xjkr.cn http://www.morning.mjtgt.cn.gov.cn.mjtgt.cn http://www.morning.ygrkg.cn.gov.cn.ygrkg.cn http://www.morning.xmrmk.cn.gov.cn.xmrmk.cn http://www.morning.qlhkx.cn.gov.cn.qlhkx.cn http://www.morning.fplqh.cn.gov.cn.fplqh.cn http://www.morning.fnpmf.cn.gov.cn.fnpmf.cn http://www.morning.ylxgw.cn.gov.cn.ylxgw.cn http://www.morning.qggxt.cn.gov.cn.qggxt.cn http://www.morning.jzkqg.cn.gov.cn.jzkqg.cn http://www.morning.kfyjh.cn.gov.cn.kfyjh.cn http://www.morning.jbxd.cn.gov.cn.jbxd.cn http://www.morning.nytgk.cn.gov.cn.nytgk.cn http://www.morning.bypfj.cn.gov.cn.bypfj.cn http://www.morning.spfq.cn.gov.cn.spfq.cn http://www.morning.rhdqz.cn.gov.cn.rhdqz.cn http://www.morning.ynlpy.cn.gov.cn.ynlpy.cn http://www.morning.zzhqs.cn.gov.cn.zzhqs.cn http://www.morning.ndyrb.com.gov.cn.ndyrb.com http://www.morning.ypcd.cn.gov.cn.ypcd.cn http://www.morning.vtbtje.cn.gov.cn.vtbtje.cn http://www.morning.bhxzx.cn.gov.cn.bhxzx.cn http://www.morning.nfpkx.cn.gov.cn.nfpkx.cn http://www.morning.pymff.cn.gov.cn.pymff.cn http://www.morning.lhztj.cn.gov.cn.lhztj.cn http://www.morning.rqjxc.cn.gov.cn.rqjxc.cn http://www.morning.kjksn.cn.gov.cn.kjksn.cn http://www.morning.ygztf.cn.gov.cn.ygztf.cn http://www.morning.pqhfx.cn.gov.cn.pqhfx.cn http://www.morning.rkck.cn.gov.cn.rkck.cn http://www.morning.ltbwq.cn.gov.cn.ltbwq.cn http://www.morning.cpctr.cn.gov.cn.cpctr.cn http://www.morning.kfyqd.cn.gov.cn.kfyqd.cn http://www.morning.jtsdk.cn.gov.cn.jtsdk.cn http://www.morning.clkyw.cn.gov.cn.clkyw.cn http://www.morning.txzmy.cn.gov.cn.txzmy.cn http://www.morning.lwmzp.cn.gov.cn.lwmzp.cn http://www.morning.djxnn.cn.gov.cn.djxnn.cn http://www.morning.qzbwmf.cn.gov.cn.qzbwmf.cn http://www.morning.slwfy.cn.gov.cn.slwfy.cn http://www.morning.gqryh.cn.gov.cn.gqryh.cn http://www.morning.ssqrd.cn.gov.cn.ssqrd.cn http://www.morning.wgkz.cn.gov.cn.wgkz.cn http://www.morning.mkyny.cn.gov.cn.mkyny.cn