- 1、本文档共13页,可阅读全部内容。
- 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
- 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
- 5、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
- 6、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们。
- 7、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
- 8、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
传统指针的缺陷
传统指针的缺陷 容易导致内存泄漏void f() { T* p= new T;} 可能导致内存泄漏的错误 忘了delete p 函数意外退出 ,例如出现exception。 当对象需要在多个函数或者模块中传递时,难以决定何时删除这个对象 例如:用户调用模块A的方法生成一个对象c,那么这个对象是由用户还是由模块A来释放呢? 如果用户释放,缺点: 增加了用户的负担。 用户可能会忘记释放。 如果模块A释放,模块A何时释放这个对象c? 一种改进的指针类auto_ptr 代码见auto_ptr 优点:指针变量生存周期结束后,自动释放内存。 缺点:将一个auto_ptr复制给另一个auto_ptr后,原来的auto_ptr将不再指向任何对象。所以是一种破坏性复制语义。和原生指针的语义不一致 智能指针 能不能设计一种与原生指针语义相同,但是可以自动释放内存的指针呢? 分析auto_ptr: 若多个auto_ptr指向同一个对象,只有当最后一个auto_ptr结束生存周期后,才能释放这个对象,但是如何能知道那个auto_ptr是最后一个结束生存周期呢? 解决方案之一 为每个对象设置一个计数器,每当一个指针指向它时,计数器加1,指针结束身存周期后计数器减1。 关于计数器的两个问题 一个计数器应该对应一个对象,那么这个计数器应该放在哪里呢? 放在对象内部?需要侵入对象,修改对象内部结构,通用性不强。 放在对象的外部?那么如何与对象关联起来呢? 当指针指向对象或者结束生存周期后,如何修改对象所关联的计数器呢? 一种解决方法 为了保持通用性,尽可能不破坏对象的封装,计数器一般应该放在对象的外部,为了保证与对象的生存周期一致,计数器应该放在堆中。 对象A第一次付给某个指针p时,应该同时在堆中产生一个含有计数器的对象counter,counter应该保存对象A的地址。指针p则保存counter的地址。 当指针p赋值给另外一个指针q时,q应该保存counter的地址。同时给counter中计数器加1。 当p结束生存周期或者指向其他的对象时,counter中的计数器减1。 当 通过指针p访问对象A时,按照p-counter-A的方式访问 当counter中的计数器值为0时,表示没有任何指针指向对象A,应该自动将对象A删除。 smart_ptr主要成员1 typedef X XType; class smart_ptr { public: typedef XType* PointerType; typedef XType ReferenceType; smart_ptr(); smart_ptr(const PointerType data); smart_ptr(const smart_ptr sp); virtual ~smart_ptr() ; smart_ptr operator=(const PointerType data); smart_ptr operator=(const smart_ptr sp); …… smart_ptr主要成员2 …… PointerType get_ptr () const; //返回原始指针 int user_count() const; //返回指向当前对象的智能指针数 ReferenceType operator*() const; PointerType operator-() const;operator void*() const // 之所以要两个类型转换,主要是为了方式出现误删除 delete smart_ptr的情况 operator PointerType() const; // 类型转换 private: counter *p_counter; }; 其他的函数 operator== operator!= operator= operator= operator operator smart_ptr的缺点 最大的缺点是无法应付循环引用,对于分别属于C的智能指针A和属于D的智能指针B,如果出现类似A指向D,B指向C的情况,C和D都不会被释放掉。 非侵入式的智能指针占用内存较多 两次寻址速度稍慢。 结束语 这里所展示的仅仅是一个教学用的玩具,工业级别的智能指针要考虑的因素很多,功能复杂。以loki库所设计的智能指针为例,其代码多达1400余行。关于智能指针设计的详细讨论可以参见《modern C++ design》(中文译名《C++ 设计新思维:范型编程与设计模式之应用》)第7章 * * *
文档评论(0)