﻿<?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++博客-sqrabs-文章分类-神乎其技</title><link>http://www.cppblog.com/sqrabs/category/12989.html</link><description /><language>zh-cn</language><lastBuildDate>Sun, 07 Feb 2010 10:00:57 GMT</lastBuildDate><pubDate>Sun, 07 Feb 2010 10:00:57 GMT</pubDate><ttl>60</ttl><item><title>boost::enable_shared_from_this的部分实现研究</title><link>http://www.cppblog.com/sqrabs/articles/107036.html</link><dc:creator>天色已晚</dc:creator><author>天色已晚</author><pubDate>Tue, 02 Feb 2010 10:57:00 GMT</pubDate><guid>http://www.cppblog.com/sqrabs/articles/107036.html</guid><wfw:comment>http://www.cppblog.com/sqrabs/comments/107036.html</wfw:comment><comments>http://www.cppblog.com/sqrabs/articles/107036.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/sqrabs/comments/commentRss/107036.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/sqrabs/services/trackbacks/107036.html</trackback:ping><description><![CDATA[原文转自我自己的Blog：http://2years.net/2010/02/02/enable-shared-from-this-research/<br><br>
<p>shared_ptr是boost库实现的几个智能指针中最重要的，其使用引用计数机制来管理资源。</p>
<p>如果一个类由shared_ptr管理，而在这个类的某个方法又需要传出一个指向自身的指针，那么这个指针也必须被shared_ptr所管理。
boost库的实现方法为让被管理类继承boost::enable_shared_from_this类，此后通过shared_from_this函
数获得指向自身的shared_ptr。</p>
<p>enable_shared_from_this实质上是把一个weak_ptr作为被管理类的成员，其观察资源使用情况，在调用
shared_from_this函数时就是通过这个weak_ptr生成了一个shared_ptr。研读
enable_shared_from_this机制的实现时，发现以下代码：</p>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #008080;">1</span>&nbsp;<span style="color: #000000;">template</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;X,&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;Y,&nbsp;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;T&nbsp;</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br></span><span style="color: #008080;">2</span>&nbsp;<span style="color: #000000;">inline&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;sp_enable_shared_from_this(&nbsp;boost::shared_ptr</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">X</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;ppx,&nbsp;Y&nbsp;</span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;py,&nbsp;boost::enable_shared_from_this</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">&nbsp;T&nbsp;</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;pe&nbsp;)<br></span><span style="color: #008080;">3</span>&nbsp;<span style="color: #000000;">{<br></span><span style="color: #008080;">4</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">(&nbsp;pe&nbsp;</span><span style="color: #000000;">!=</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">0</span><span style="color: #000000;">&nbsp;)<br></span><span style="color: #008080;">5</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;{<br></span><span style="color: #008080;">6</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pe</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">_internal_accept_owner(&nbsp;ppx,&nbsp;const_cast</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">&nbsp;Y</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">&gt;</span><span style="color: #000000;">(&nbsp;py&nbsp;)&nbsp;);<br></span><span style="color: #008080;">7</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;}<br></span><span style="color: #008080;">8</span>&nbsp;<span style="color: #000000;">}</span></div>
这个函数就是设置被管理类中的weak_ptr的。那么这个函数什么时候被调用呢？是在shared_ptr的构造函数中：
<br>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #008080;">1</span>&nbsp;<span style="color: #000000;">template</span><span style="color: #000000;">&lt;</span><span style="color: #0000ff;">class</span><span style="color: #000000;">&nbsp;Y</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br></span><span style="color: #008080;">2</span>&nbsp;<span style="color: #000000;"></span><span style="color: #0000ff;">explicit</span><span style="color: #000000;">&nbsp;shared_ptr(&nbsp;Y&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;p&nbsp;):&nbsp;px(&nbsp;p&nbsp;),&nbsp;pn(&nbsp;p&nbsp;)&nbsp;</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;Y&nbsp;must&nbsp;be&nbsp;complete</span><span style="color: #008000;"><br></span><span style="color: #008080;">3</span>&nbsp;<span style="color: #008000;"></span><span style="color: #000000;">{<br></span><span style="color: #008080;">4</span>&nbsp;<span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;boost::detail::sp_enable_shared_from_this(&nbsp;</span><span style="color: #0000ff;">this</span><span style="color: #000000;">,&nbsp;p,&nbsp;p&nbsp;);<br></span><span style="color: #008080;">5</span>&nbsp;<span style="color: #000000;">}</span></div>
<p>这里比较奇怪的地方就是sp_enable_shared_from_this这个函数是始终被调用的，但是如果被管理类没有继承自
enable_shared_from_this，那这个调用肯定是通不过的，因为指向普通类型Y的指针p不能转型为指向
enable_shared_from_this类的指针。继续翻代码，发现sp_enable_shared_from_this函数的一个重载：<br>
</p>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: #000000;">inline&nbsp;</span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;sp_enable_shared_from_this(&nbsp;&#8230;&nbsp;){}</span></div>
<br>
原来这个地方充分利用了函数重载发现机制，如果被管理类继承自enable_shared_from_this，那么第一个
sp_enable_shared_from_this就是最合适的，shared_ptr的构造函数中会调用这个版本。否则，就会调用第二个
sp_enable_shared_from_this函数也就是最通用化的版本，因为&#8230;就是不定参数，它可以接受任何传入的类型。而这个参数又是一个空
函数，什么事都不会发生。
<p>&#160;</p>
<p>这种实现方式也避免了效率的降低，因为2个sp_enable_shared_from_this都是内联inline的，这就保证了如果不需要设置weak_ptr那么不会有任何函数调用发生。</p>
<br><br> <img src ="http://www.cppblog.com/sqrabs/aggbug/107036.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/sqrabs/" target="_blank">天色已晚</a> 2010-02-02 18:57 <a href="http://www.cppblog.com/sqrabs/articles/107036.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>