﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-一如技网-随笔分类-C++语言</title><link>http://www.cppblog.com/bossbird/category/7926.html</link><description>-爱无止境</description><language>zh-cn</language><lastBuildDate>Sun, 21 Sep 2008 19:17:38 GMT</lastBuildDate><pubDate>Sun, 21 Sep 2008 19:17:38 GMT</pubDate><ttl>60</ttl><item><title>[转]C++深度探索系列：智能指针(Smart Pointer) [一]</title><link>http://www.cppblog.com/bossbird/archive/2008/09/22/62434.html</link><dc:creator>kzhang</dc:creator><author>kzhang</author><pubDate>Sun, 21 Sep 2008 16:37:00 GMT</pubDate><guid>http://www.cppblog.com/bossbird/archive/2008/09/22/62434.html</guid><wfw:comment>http://www.cppblog.com/bossbird/comments/62434.html</wfw:comment><comments>http://www.cppblog.com/bossbird/archive/2008/09/22/62434.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/bossbird/comments/commentRss/62434.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/bossbird/services/trackbacks/62434.html</trackback:ping><description><![CDATA[<p>主题索引：</p>
<p>一、剖析C++标准库智能指针(std::auto_ptr)<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 1.Do you Smart Pointer?<br>&nbsp;&nbsp;&nbsp; 2.std::auto_ptr的设计原理<br>&nbsp;&nbsp;&nbsp; 3.std::auto_ptr高级使用指南<br>&nbsp;&nbsp;&nbsp; 4.你是否觉得std::auto_ptr还不够完美?</p>
<p>二、C++条件,寻找构造更强大的智能指针(Smart Pointer)的<br>&nbsp;&nbsp;&nbsp; 策略<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 1.支持引用记数的多种设计策略<br>&nbsp;&nbsp;&nbsp; 2.支持处理多种资源<br>&nbsp;&nbsp;&nbsp; 3.支持Subclassing<br>&nbsp;&nbsp;&nbsp; 4.支持多线程条件下,线程安全的多种设计策略<br>&nbsp;&nbsp;&nbsp; 5.其它多种特殊要求下,再构造</p>
<p>三、Generic Programming基础技术和Smart Pointer<br>&nbsp;&nbsp;&nbsp; 1.回首处理资源中的Traits技术<br>&nbsp;&nbsp;&nbsp; 2.回首多线程支持的设计</p>
<p><br>四、COM实现中,Smart Pointer设计原理</p>
<p><br>五、著名C++库(标准和非标准)中的Smart Pointer现状</p>
<p>---------------------------------------------------------------------</p>
<p><br><font color=#e73408>一、剖析C++标准库智能指针(std::auto_ptr)<br></font>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;<strong><font color=#721717 size=4> 1.Do you Smart Pointer?<br></font></strong><font color=#00440e><br></font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Smart Pointer,中文名：智能指针, 舶来品?<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 不可否认,资源泄露(resource leak)曾经是C++程序的一大噩梦.垃圾回收<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 机制(Garbage Collection)一时颇受注目.然而垃圾自动回收机制并不能<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 满足内存管理的即时性和可视性,往往使高傲的程序设计者感到不自在.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 况且,C++实现没有引入这种机制.在探索中,C++程序员创造了锋利的<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "Smart Pointer".一定程度上,解决了资源泄露问题.</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 也许,经常的,你会写这样的代码：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //x拟为class:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class x{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int m_Idata;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; x(int m_PARAMin):m_Idata(m_PARAMin){}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void print(){ cout&lt;&lt;m_Idata&lt;&lt;endl; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .....<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void fook(){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; x* m_PTRx = new A(m_PARAMin);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_PTRx-&gt;DoSomething();&nbsp;&nbsp;&nbsp;&nbsp; //#2<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; delete m_PTRx;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 是的,这里可能没什么问题.可在复杂、N行、m_PTRclassobj所指对象生命周<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 期要求较长的情况下,你能保证你不会忘记delete m_PTRclassobj吗?生活中,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 我们往往不应该有太多的口头保证,我们需要做些真正有用的东西.还有一个<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 更敏感的问题：异常.假如在#2方法执行期异常发生,函数执行终止,那么new<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 出的对象就会泄露.于是,你可能会说：那么就捕获异常来保证安全性好了.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 你写这样的程式：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void fook(){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; A* m_PTRx = new A(m_PARAMin);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_PTRx-&gt;DoSomething();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; catch(..){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; delete m_PTRx;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; delete m_PTRx;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 哦!天哪!想象一下,你的系统,是否会象专为捕获异常而设计的.</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 一天,有人给你建议:"用Smart Pointer,那很安全.".你可以这样重写你的程序：<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void fook(){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; auto_ptr&lt;x&gt; m_SMPTRx(new x(m_PARAMin));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_SMPTRx-&gt;DoSomething();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; OK!你不太相信.不用delete吗?<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 是的.不用整天提心吊胆的问自己:"我全部delete了吗?",而且比你的delete<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 策略更安全.</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 然后,还有人告诉你,可以这样用呢：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ok1.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; auto_ptr&lt;x&gt; m_SMPTR1(new x(m_PARAMin)); <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; auto_ptr&lt;x&gt; m_SMPTR2(m_SMPTR1);&nbsp; //#2<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; May be you can code #2 like this :<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; auto_ptr&lt;x&gt; m_SMPTR2;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_SMPTR2 = m_SMPTR1;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ok2.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; auto_ptr&lt;int&gt; m_SMPTR1(new int(32));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ok3.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; auto_ptr&lt;int&gt; m_SMPTR1;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_SMPTR1 = auto_ptr&lt;int&gt;(new int(100));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 也可以：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; auto_ptr&lt;int&gt; m_SMPTR1(auto_ptr&lt;int&gt;(new int(100)));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ok4.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; auto_ptr&lt;x&gt; m_SMPTR1(new x(m_PARAMin));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_SMPTR1.reset(new x(m_PARAMin1));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ok5.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; auto_ptr&lt;x&gt; m_SMPTR1(new x(m_PARAMin));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; auto_ptr&lt;x&gt; m_SMPTR2(m_SMPTR.release());<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout&lt;&lt;(*m_SMPTR2).m_Idata&lt;&lt;endl;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ok6.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; auto_ptr&lt;int&gt; fook(){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return auto&lt;int&gt;(new int(100));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ok7.............and so on<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 但不可这样用：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; no1.&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char* chrarray = new char[100];<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; strcpy(chrarray,"I am programming.");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; auto_ptr&lt;char*&gt; m_SMPTRchrptr(chrarray);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //auto_ptr并不可帮你管理数组资源&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; no2.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; vector&lt;auto_ptr&lt;x&gt;&gt; m_VECsmptr;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_VECsmptr.push_back(auto_ptr&lt;int&gt;(new int(100)));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //auto_ptr并不适合STL内容.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; no3.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; const auto_ptr&lt;x&gt; m_SMPTR1(new x(100));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; auto_ptr&lt;x&gt; m_SMPTR(new x(200));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; no4.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; x m_OBJx(300);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; auto_ptr&lt;x&gt; m_SMPTR(&amp;m_OBJx);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; no5<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; x* m_PTR = new x(100);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; auto_ptr&lt;x&gt; m_SMPTR = m_pTR;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; no6..........and so on</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 预先提及所有权的问题,以便下面带着疑问剖析代码?</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; power1.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; auto_ptr&lt;x&gt; m_SMPTR1(new x(100));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; auto_ptr&lt;x&gt; m_SMPTR2 = m_SMPTR1;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_SMPTR2-&gt;print();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //输出：100.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_SMPTR1-&gt;print();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //!! 非法的.</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; power2.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; auto_ptr&lt;x&gt; m_SMPTR(new x(100));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; auto_ptr&lt;x&gt; returnfun(auto_ptr&lt;x&gt; m_SMPTRin){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return m_SMPTRin;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; auto_ptr&lt;x&gt; = returnfun(m_SMPTR);&nbsp; //#5</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //在上面的#5中,我要告诉你对象所有权转移了两次.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //什么叫对象所有权呢?<br>&nbsp;&nbsp; <br>&nbsp;<font size=4><font color=#882222><strong>&nbsp;&nbsp; 2. std::auto_ptr的设计原理</strong><br></font></font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 上面的一片正确用法,它们在干些什么?<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 一片非法,它们犯了什么罪?<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 一片什么所有权转移,它的内部机智是什么?<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 哦!一头雾水?下面我们就来剖析其实现机制.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 基础知识：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; a.智能指针的关键技术：在于构造栈上对象的生命期控制<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 堆上构造的对象的生命期.因为在智能指针的内部,存储<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 着堆对象的指针,而且在构析函数中调用delete行为.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 大致机构如下：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; x* m_PTRx = new x(100);//#1<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; template&lt;typename T&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; auto_ptr{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; T* m_PTR;//维护指向堆对象的指针,在auto_ptr定位后&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ....&nbsp;&nbsp;&nbsp;&nbsp; //它应该指向#1构造的对象,即拥有所有权.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ~auto(){ delete m_PTR; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ....<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; b.所有权转移之说<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 上面曾有一非法的程式片段如下：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; auto_ptr&lt;x&gt; m_SMPTR1(new x(100));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; auto_ptr&lt;x&gt; m_SMPTR2 = m_SMPTR1;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_SMPTR2-&gt;print();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //输出：100.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_SMPTR1-&gt;print();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //!! 非法的.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 按常理来说,m_SMPTR-&gt;print();怎么是非法的呢?<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 那是因为本来,m_SMPTR1维护指向new x(100)的指针,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 可是m_SMPTR2 = m_SMPTR1;auto_ptr内部机制使得m_SMPTR1将对象的地址<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 传给m_SMPTR2,而将自己的对象指针置为0.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 那么自然m_SMPTR-&gt;print();失败.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这里程序设计者要负明显的职责的.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 那么auto_ptr为什么采取这样的策略：保证所有权的单一性.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 亦保证了系统安全性.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如果多个有全权的auto_ptr维护一个对象,那么在你消除一个<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; auto_ptr时,将导致多个auto_ptr的潜在危险.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 下面我们以SGI-STL的auto_ptr设计为样本(去掉了无关分析的宏),来剖析其原理.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #1&nbsp; template &lt;class _Tp&gt; class auto_ptr {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #2&nbsp; private:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #3&nbsp; _Tp* _M_ptr;&nbsp; //定义将维护堆对象的指针</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #4&nbsp; public:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #5&nbsp; typedef _Tp element_type;&nbsp; //相关类型定义<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #6&nbsp; explicit auto_ptr(_Tp* __p = 0) __STL_NOTHROW : _M_ptr(__p) {}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #7&nbsp; auto_ptr(auto_ptr&amp; __a) __STL_NOTHROW : _M_ptr(__a.release()) {}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #8&nbsp; template &lt;class _Tp1&gt; auto_ptr(auto_ptr&lt;_Tp1&gt;&amp; __a) __STL_NOTHROW<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : _M_ptr(__a.release()) {}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //#6、#7、#8是auto_ptr构造函数的三个版本.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //#6注释：传入对象的指针,构造auto_ptr.explicit关键字:禁止隐式转换.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这就是ok2正确,而no5(隐式转换)错误的原因.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //#7注释：拷贝构造函数.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 传入auto_ptr实例,构造auto_ptr. ok1、ok3使用了这个构造式.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 它是一个很关键的构造函数,在具体情况下,我们再分析<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //#8注释：auto_ptr的模板成员,可在继承对象重载的基础上,实现特殊功能.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp; 举例：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp; class A{ public: <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; virtual void fook(){cout&lt;&lt;"I am programming"&lt;&lt;endl;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*..........*/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp; class B : public A {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; virtual void fook(){ cout&lt;&lt;"I am working"&lt;&lt;endl;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*...........*/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; };&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp; auto_ptr&lt;A&gt; m_SMPTRa(new A(33));//实质：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp; auto_ptr&lt;B&gt; m_SMPTRb(m_SMPTRa); //基类的指针可以赋给派生类的指针&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp; auto_ptr&lt;B&gt; m_SMPTRb(new B(44));//实质：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp; auto_ptr&lt;A&gt; m_SMPTRa(m_SMPTRb); //派生类的指针不可赋给基类的指针<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp; auto_ptr&lt;A&gt; m_SMPTRa(new B(33));&nbsp; // ok!&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp; m_SMPTRa-&gt;fook()将调用派生类B的fook()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp; m_SMPTRa-&gt;A::fook()将调用基类A的fook()<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp; auto_ptr&lt;B&gt; m_SMPTRb(new A(33));&nbsp; // wrong!<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #9&nbsp; auto_ptr&amp; operator=(auto_ptr&amp; __a) __STL_NOTHROW {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #10 if (&amp;__a != this) { delete _M_ptr;&nbsp; _M_ptr = __a.release(); }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #11 return *this;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #12 }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #13 template &lt;class _Tp1&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #14 auto_ptr&amp; operator=(auto_ptr&lt;_Tp1&gt;&amp; __a) __STL_NOTHROW {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #15 if (__a.get() != this-&gt;get()) { delete _M_ptr; _M_ptr = __a.release(); }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #16 return *this;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #16 }&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // #9~~#16 两个版本的指派函数.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; delete _M_ptr; 在指派前,销毁原维护的对象.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _a.release() ; release操作,详细代码参见#20~~#23.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 用于*this获得被指派对象,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 且将原维护auto_ptr置空.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp; no3使用了第一种指派.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp; 而权限转移正是_a.release()的结果.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #17 ~auto_ptr() __STL_NOTHROW { delete _M_ptr; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //构析函数.消除对象.注意这里对对象的要求!<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #17 _Tp&amp; operator*() const __STL_NOTHROW {&nbsp; return *_M_ptr; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #18 _Tp* operator-&gt;() const __STL_NOTHROW { return _M_ptr;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #19 _Tp* get() const __STL_NOTHROW { return _M_ptr; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp; 操作符重载.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // #17注释：提领操作(dereference),获得对象. 见ok5用法.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // #18注释：成员运算符重载,返回对象指针.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // #19注释：普通成员函数.作用同于重载-&gt;运算符<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #20 _Tp* release() __STL_NOTHROW {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #21 _Tp* __tmp = _M_ptr;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #22 _M_ptr = 0;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #23 return __tmp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //上面已经详解&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #24 void reset(_Tp* __p = 0) __STL_NOTHROW {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #25 delete _M_ptr;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #26 _M_ptr = __p;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //传入对象指针,改变auto_ptr维护的对象<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 且迫使auto_ptr消除原来维护的对象<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 见ok3用法.</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // According to the C++ standard, these conversions are required.&nbsp; Most<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // present-day compilers, however, do not enforce that requirement---and, <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // in fact, most present-day compilers do not support the language <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // features that these conversions rely on.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //下面这片段用于类型转化,目前没有任何编译器支持<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //具体技术细节不诉.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #ifdef __SGI_STL_USE_AUTO_PTR_CONVERSIONS</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #27 private:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #28 template&lt;class _Tp1&gt; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #29 struct auto_ptr_ref { _Tp1* _M_ptr; auto_ptr_ref(_Tp1* __p) : _M_ptr(__p) {}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; };</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #30 public:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #31 auto_ptr(auto_ptr_ref&lt;_Tp&gt; __ref) __STL_NOTHROW<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : _M_ptr(__ref._M_ptr) {}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #32 template &lt;class _Tp1&gt; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #33 operator auto_ptr_ref&lt;_Tp1&gt;() __STL_NOTHROW <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #34 { return auto_ptr_ref&lt;_Tp&gt;(this-&gt;release()); }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #35 template &lt;class _Tp1&gt; operator auto_ptr&lt;_Tp1&gt;() __STL_NOTHROW<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #36 { return auto_ptr&lt;_Tp1&gt;(this-&gt;release()); }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #37 #endif /* __SGI_STL_USE_AUTO_PTR_CONVERSIONS */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #38 };<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; OK!就是这样了.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 正如上面原理介绍处叙说,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 你需要正视两大特性：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1.构造栈对象的生命期控制堆上构造的对象的生命期<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2.通过release来保证auto_ptr对对象的独权.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp; 在我们对源码分析的基础上,重点看看：<br>&nbsp;&nbsp;&nbsp;&nbsp; no系列错误在何处?<br>&nbsp;&nbsp;&nbsp;&nbsp; no1.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 我们看到构析函数template&lt;class _Tp&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ~auto_ptr() _STL_NOTHROW<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { delete _M_ptr; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 所以它不能维护数组,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 维护数组需要操作：delete[] _M_ptr;<br>&nbsp;&nbsp;&nbsp;&nbsp; no2.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 先提部分vector和auto_ptr代码：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; a.提auto_ptr代码<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; auto_ptr(auto_ptr&amp; __a) __STL_NOTHROW : _M_ptr(__a.release()) {}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; b.提vector代码<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Part1:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void push_back(const _Tp&amp; __x) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (_M_finish != _M_end_of_storage) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; construct(_M_finish, __x);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ++_M_finish;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _M_insert_aux(end(), __x);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Part2:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; template &lt;class _T1, class _T2&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; inline void construct(_T1* __p,</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //++++++++++++++++++++++++++++++++ <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; const _T2&amp; __value) { +<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //++++++++++++++++++++++++++++++++<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp; new (__p) _T1(__value);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; +<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //++++++++++++++++++++++++++++++++</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Part3.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; template &lt;class _Tp, class _Alloc&gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; vector&lt;_Tp, _Alloc&gt;::_M_insert_aux<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (iterator __position,</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //++++++++++++++++++++++++++++++++ <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; const _Tp&amp; __x)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ++<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //++++++++++++++++++++++++++++++++&nbsp;&nbsp; <br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (_M_finish != _M_end_of_storage) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; construct(_M_finish, *(_M_finish - 1));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ++_M_finish;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //++++++++++++++++++++++++++++++++<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp;&nbsp; _Tp __x_copy = __x;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; +<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //++++++++++++++++++++++++++++++++</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; copy_backward(__position, _M_finish - 2, _M_finish - 1);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *__position = __x_copy;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; const size_type __old_size = size();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; const size_type __len = __old_size != 0 ? 2 * __old_size : 1;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; iterator __new_start = _M_allocate(__len);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; iterator __new_finish = __new_start;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; __STL_TRY {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; __new_finish = uninitialized_copy<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (_M_start, __position, __new_start);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; construct(__new_finish, __x);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ++__new_finish;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; __new_finish = uninitialized_copy<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (__position, _M_finish, __new_finish);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; __STL_UNWIND((destroy(__new_start,__new_finish), <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _M_deallocate(__new_start,__len)));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; destroy(begin(), end());<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _M_deallocate(_M_start, _M_end_of_storage - _M_start);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _M_start = __new_start;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _M_finish = __new_finish;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; _M_end_of_storage = __new_start + __len;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 从提取的vector代码,Part1可看出,push_back的操作行为.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 兵分两路,可是再向下看,你会发现,无一例外,都<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 通过const _Tp&amp; 进行拷贝行为,那么从auto_ptr提出的片段就<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 派上用场了. <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 可你知道的,auto_ptr总是坚持对对象的独权.那必须修改<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 原来维护的对象,而vector行为要求const _Tp&amp;,这样自然会产生<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 问题.一般编译器是可以发觉这种错误的.</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 其实,STL所有的容器类都采用const _Tp&amp;策略.<br>&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + 看了sutter和Josuttis的两篇文章中,都提及：&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; +<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + STL容器不支持auto_ptr原因在于copy的对象只是获得所有权的对象, +<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + 这种对象不符合STL的要求.可是本人总感觉即时不是真正的复制对象,+<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + 但我用vector&lt;auto_ptr&lt;x&gt; &gt;的目的就在于维护对象,并不在乎&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; +<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + 所谓的完全对象.而且我用自己写的Smart Pointer配合STL容器工作, +<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; + 很正常.那需要注意的仅仅是const问题.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; +<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; +&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; +<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; no3.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这个也是auto_ptr隐含的所有权问题引起的.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; const auto_ptr不允许修改.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 随便提及：const对象不代表对象一点不可以改变.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在两种const语义下,都有方法修改对象或对象内部指针维护的对象<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 或其它资源.<br>&nbsp;&nbsp;&nbsp;&nbsp; no4.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 再看auto_ptr的构析函数.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; delete不可以消除栈上资源.</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; no5.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 依赖传入对象指针的构造函数被声明为explicit,禁止隐式转换.</p>
<p>&nbsp;&nbsp;&nbsp; <br>&nbsp;<font color=#0e3616><strong>&nbsp;<font color=#852b14 size=4>&nbsp; 3.auto_ptr高级使用指南</font></strong></font><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; a.类成员auto_ptr,禁止构造函数以构建"完全对象"<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Programme1:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct Structx{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int m_Idata;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char m_CHRdata;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /* and so on */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; };<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 出于对象编程的理念,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 我们将Structx打造成包裹类：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class StructWrapper{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Structx* m_STRTxptr;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; StructWrapper():m_STRTxptr(new Structx){}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ~StructWrapper(){delete m_SMRTxptr; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void Soperator1(){ /* 针对Structx对象的特性操作 */}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void Soperator2(){ /* 针对Structx对象的特性操作 */}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*&nbsp; and so on */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Programme2:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; class StructWrapper{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; auto_ptr&lt;Structx&gt; m_SMPTRx;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; StructWrapper():m_SMPTRAx(new Structx){}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void Soperator1(){ /* 针对Structx对象的特性操作 */}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void Soperator2(){ /* 针对Structx对象的特性操作 */}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /*&nbsp; and so on */<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Programme3:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; StructWrapper::StructWrapper(const StructWrapper&amp; other)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : M_SMPTRx(new Struct(*other.m_SMPTRx)) { }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; StructWrapper&amp; StructWrapper::operator=(const StructWrapper &amp;other){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *m_SMPTRx = *other.m_SMPTRx;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; };</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 处于对构建于堆中的对象(new Structx)智能维护的需要.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 我们将programme1改造为programme2：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 不错,对象是可以智能维护了.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 对于包裹类(StructWrapper)你是否会有这样的构造或指派操作：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; StructWrapper m_SMPTRWrapper2(m_SMPTRWrapper1);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; StructWrapper mSMPTRWrapper2 = m_SMPTRWrapper1; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 那么请注意：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 当你坦然的来一个：M_SMPTRWrapper1-&gt;Soperator1();的时候,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 系统崩溃了.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 不必惊讶,所有权还是所有权问题.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 问一下自己：当programme2默认拷贝构造函数作用时,又调用了auto_ptr的<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 默认构造函数,那么auto_ptr所有的默认行为都遵循独权策略.对,就这样.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m_SMPTRWrapper1的对象所有权转移给了m_SMPTRWrapper2.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; M_SMPTRWrapper1-&gt;Soperator1();那么操作变成了在NULL上的.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 哦!系统不崩溃才怪.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 那么你需要想,programme3那样利用auto_ptr的提领操作符自己的<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 构造"完全对象".</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; b.利用const关键字,防止不经意的权限转移<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 从上面的叙述,你可看出,所有权转移到处可以酿成大祸.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 而对于一般应用来说,独权又是很好的安全性策略.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 那么我们就用const来修饰auto_ptr,禁止不经意的错误.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 当然上面提及：并不代表auto_ptr是不可修改的.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 处于需要,从两种const语义,你都可实现修改.</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 然,你还希望在函数传入传出auto_ptr那么你可传递auto_ptr的引用,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 那就万无一失了: void fook(const auto_ptr&lt;x&gt;&amp; m_PARAMin);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在返回后赋予其它时,使用引用是不行的.你得用指针.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 因为引用无论作为lvalue还是rvaluev,都会调用构造或指派函数.</p>
<p><br>&nbsp;&nbsp;<font color=#294422 size=4><strong>&nbsp;<font color=#721717> 4.你是否觉得std::auto_ptr还不够完美</font></strong></font><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在实践中,std::auto_ptr能满足你的需求吗?&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Andrei Alexandrescu在一篇文章中,提及：有关Smart Pointer的技术就像<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 巫术.Smart Pointer作为C++垃圾回收机制的核心,它必须足够强大的、具有工业强度和安全性.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 但为了可一劳永逸我们还需要披荆斩棘继续探索.</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 下面在需求层面上,我们思索一下我们的智能指针还需要些什么?<br>&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; a. std::auto_ptr 能够处理数组吗?我们可以用智能指针来管理其它的资源吗?<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 譬如一个线程句柄、一个文件句柄 and so on !<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; b. 对于我们的对象真的永远实行独权政策吗?<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; c. Our 智能指针还需要在继承和虚拟层面上发挥威力 !<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; d. 往往,需要扩展Our 智能指针的功能成员函数来满足动态的需要 !<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e. 也许,你需要的还很多.</p>
<p>---------------------------------------------------------------<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [下续] </p>
<p>二、C++条件,寻找构造更强大的智能指针(Smart Pointer)的<br>&nbsp;&nbsp;&nbsp; 策略<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; 1.支持引用记数的多种设计策略<br>&nbsp;&nbsp;&nbsp; 2.支持处理多种资源<br>&nbsp;&nbsp;&nbsp; 3.支持Subclassing<br>&nbsp;&nbsp;&nbsp; 4.支持多线程条件下,线程安全的多种设计策略<br>&nbsp;&nbsp;&nbsp; 5.其它多种特殊要求下,再构造</p>
<p>三、Generic Programming基础技术和Smart Pointer<br>&nbsp;&nbsp;&nbsp; 1.回首处理资源中的Traits技术<br>&nbsp;&nbsp;&nbsp; 2.回首多线程支持的设计</p>
<p><br>四、COM实现中,Smart Pointer设计原理</p>
<p><br>五、著名C++库(标准和非标准)中的Smart Pointer现状</p>
<p>-----------------------------------------------------------</p>
<p>--------------------------------------------------------------<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 郑重声明：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 允许复制、修改、传递或其它行为<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 但不准用于任何商业用途.<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 写于&nbsp; 20/3/2003<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 最后修改： 20/3/2003<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; By RedStar81<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#56;&#49;&#95;&#82;&#101;&#100;&#83;&#116;&#97;&#114;&#64;&#49;&#54;&#51;&#46;&#99;&#111;&#109;"><u><font color=#0000ff>81_RedStar@163.com</font></u></a><br>-------------------------------------------------------------&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </p>
<img src ="http://www.cppblog.com/bossbird/aggbug/62434.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/bossbird/" target="_blank">kzhang</a> 2008-09-22 00:37 <a href="http://www.cppblog.com/bossbird/archive/2008/09/22/62434.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>