<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>babaru.net</title>
	<atom:link href="http://babaru.net/feed" rel="self" type="application/rss+xml" />
	<link>http://babaru.net</link>
	<description>Just another WordPress weblog</description>
	<lastBuildDate>Sun, 14 Jun 2009 14:30:49 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>boost::serialization 对于私有构造函数的序列化</title>
		<link>http://babaru.net/archives/14</link>
		<comments>http://babaru.net/archives/14#comments</comments>
		<pubDate>Sun, 14 Jun 2009 14:28:45 +0000</pubDate>
		<dc:creator>babaru</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[boost]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Serialization]]></category>

		<guid isPermaLink="false">http://babaru.net/?p=14</guid>
		<description><![CDATA[这两天在工作中遇到一个需求，需要将C++类序列化成XML数据文件。
熟悉C#或者Java的都应该清楚，因为有元数据和框架内置的Serialization模块的存在，将一个类的实例序列化成XML文件是相当容易的。但是C++因为没有标准库支持序列化，我转而借助boost::serialization的帮助。
boost::serialization 相当强大，一般的C++类都支持，对于STL里面的集合类型（list, vector等）也都能够很好的序列化。具体的使用方法可以查看boost的文档，应该上手还是很简单的：http://www.boost.org/doc/libs/1_39_0/libs/serialization/doc/index.html
然而现实的需求肯定不是这些基础的教程能够完全覆盖的，我就遇到了关于私有缺省构造函数的类的序列化问题。
故事是这样的：
我们项目中有一套消息接口，其中有一套预定义好的消息数据类型，举个例子：SomeMarketData，用来传输某个市场的数据。
class SomeMarketData
{
public:
SomeMarketData* CreateInstance(void) { return new SomeMarketData; }
private:
SomeMarketData(void);
SomeMarketData(SomeMarketData const&#38; aData);
SomeMarketData&#38; operator =(SomeMarketData const&#38; aData);
}
这个类的缺省构造，拷贝构造和赋值操作符都被定义为私有。我们项目中的需求是将这个类的集合类型std::vector&#60;SomeMarketData*&#62;序列化。boost::serialization支持将vector的指针元素序列化和反序列化的能力，同时对于私有构造函数也提供了一定的支持，boost的文档中提到：Boost Doc -&#62; Serialization -&#62; Reference -&#62; Serialization Concept -&#62; Pointers -&#62; Non-default Constructors http://www.boost.org/doc/libs/1_39_0/libs/serialization/doc/index.html
如果你的类的缺省构造函数是私有的，而只能通过其他有参数的构造函数来进行构造，那么可以用特化（重载）load_construct_data这个方法来改变boost框架中内置的对象构造过程，如下：
// load data required for construction and invoke constructor in place
template&#60;class Archive, class T&#62;
inline void load_construct_data(Archive &#38; ar, T * t, const unsigned int file_version){
 // [...]]]></description>
			<content:encoded><![CDATA[<p>这两天在工作中遇到一个需求，需要将C++类序列化成XML数据文件。</p>
<p>熟悉C#或者Java的都应该清楚，因为有元数据和框架内置的Serialization模块的存在，将一个类的实例序列化成XML文件是相当容易的。但是C++因为没有标准库支持序列化，我转而借助boost::serialization的帮助。</p>
<p>boost::serialization 相当强大，一般的C++类都支持，对于STL里面的集合类型（list, vector等）也都能够很好的序列化。具体的使用方法可以查看boost的文档，应该上手还是很简单的：<a title="boost::serialization documentation" href="http://www.boost.org/doc/libs/1_39_0/libs/serialization/doc/index.html">http://www.boost.org/doc/libs/1_39_0/libs/serialization/doc/index.html</a></p>
<p>然而现实的需求肯定不是这些基础的教程能够完全覆盖的，我就遇到了关于私有缺省构造函数的类的序列化问题。</p>
<p>故事是这样的：</p>
<p>我们项目中有一套消息接口，其中有一套预定义好的消息数据类型，举个例子：SomeMarketData，用来传输某个市场的数据。</p>
<p><code>class SomeMarketData</code><br />
<code>{</code><br />
<code>public:<br />
SomeMarketData* CreateInstance(void) { return new SomeMarketData; }<br />
private:<br />
SomeMarketData(void);<br />
SomeMarketData(SomeMarketData const&amp; aData);<br />
SomeMarketData&amp; operator =(SomeMarketData const&amp; aData);</code><br />
<code>}</code></p>
<p>这个类的缺省构造，拷贝构造和赋值操作符都被定义为私有。我们项目中的需求是将这个类的集合类型std::vector&lt;SomeMarketData*&gt;序列化。boost::serialization支持将vector的指针元素序列化和反序列化的能力，同时对于私有构造函数也提供了一定的支持，boost的文档中提到：Boost Doc -&gt; Serialization -&gt; Reference -&gt; Serialization Concept -&gt; Pointers -&gt; Non-default Constructors <a href="http://www.boost.org/doc/libs/1_39_0/libs/serialization/doc/index.html">http://www.boost.org/doc/libs/1_39_0/libs/serialization/doc/index.html</a></p>
<p>如果你的类的缺省构造函数是私有的，而只能通过其他有参数的构造函数来进行构造，那么可以用特化（重载）load_construct_data这个方法来改变boost框架中内置的对象构造过程，如下：</p>
<p><code>// load data required for construction and invoke constructor in place<br />
template&lt;class Archive, class T&gt;<br />
inline void load_construct_data(Archive &amp; ar, T * t, const unsigned int file_version){</code></p>
<p><code> // default just uses the default constructor to initialize<br />
// previously allocated memory.<br />
::new(t)T();<br />
}</code></p>
<p>我们的问题是，SomeMarketData并不存在任何的public的构造函数，无论是缺省还是有参数的。只有一个CreateInstance这个工厂方法可以创建这个类的实例。我尝试在load_construct_data中调用CreateInstance方法，发现并不奏效，实例t的虚表在退出这个函数之后就完全消失了，或者说就根本没有被正确构造。</p>
<p>眼尖的你肯定应该已经发现了，load_construct_data函数接受一个T（这里就是我们的SomeMarketData）的指针类型做参数，t被传入的时候，实际上是做一次指针的拷贝操作，除了::new操作符，其他的操作都无法更改t所指向的对象，也就是说我可以在这个函数内部调用 t = SomeMarketData::CreateInstance(); 来实例化t，但是退出以后，这个t并没有被传递出去，更严重的是，t在函数内实例化出来的对象反而泄漏掉了。</p>
<p>通过对boost::serialization库源码的研究，当然整个过程的复杂和痛苦就不详述了，我发现在重载了load_construct_data函数后，当有指针类型需要被反序列化构造的时候，boost会调用boost/archive/detail/iserializer.hpp 里面的 heap_allocator结构来实例化对象，其中的invoke方法就是我要寻找的。</p>
<p>找到了问题点，解决起来其实就很简单了，针对每种需要序列化的类型，特化（重载）一个heap_allocator出来就可以了，针对我们的SomeMarketData类，我可以这样写：</p>
<p><code>namespace boost { namespace archive { namespace detail { // 命名空间很重要<br />
template&lt;&gt;<br />
struct heap_allocator<br />
{<br />
static SomeMarketData * invoke(){ return SomeMarketData::CreateInstance();<br />
}<br />
};<br />
}}}</code></p>
<p>上述代码和load_construct_data的特化写在一起就可以了。</p>
]]></content:encoded>
			<wfw:commentRss>http://babaru.net/archives/14/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>用影像记录时光</title>
		<link>http://babaru.net/archives/8</link>
		<comments>http://babaru.net/archives/8#comments</comments>
		<pubDate>Sat, 06 Jun 2009 14:12:04 +0000</pubDate>
		<dc:creator>babaru</dc:creator>
				<category><![CDATA[Photos]]></category>

		<guid isPermaLink="false">http://babaru.net/?p=8</guid>
		<description><![CDATA[
这两天没事，在家里翻看朋友在flickr上面的旧照片。
开始的时候只是非常随意地浏览，寻找那些照片里面有意思的场面。然而慢慢地，翻看的过程变成一次非常奇妙的经历，流动的影像重现着一张张灿烂的笑脸，一幅幅美丽的风景，重现着那个时候，那些人们的欢乐。
年华似水，老照片是那些难忘记忆的最好记录。
]]></description>
			<content:encoded><![CDATA[<p><img src="http://farm4.static.flickr.com/3556/3556822228_3a48bb1a1a.jpg?v=0" alt="" width="500" height="335" /></p>
<p>这两天没事，在家里翻看朋友在flickr上面的旧照片。</p>
<p>开始的时候只是非常随意地浏览，寻找那些照片里面有意思的场面。然而慢慢地，翻看的过程变成一次非常奇妙的经历，流动的影像重现着一张张灿烂的笑脸，一幅幅美丽的风景，重现着那个时候，那些人们的欢乐。</p>
<p>年华似水，老照片是那些难忘记忆的最好记录。</p>
]]></content:encoded>
			<wfw:commentRss>http://babaru.net/archives/8/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>那段故事从此开始</title>
		<link>http://babaru.net/archives/5</link>
		<comments>http://babaru.net/archives/5#comments</comments>
		<pubDate>Fri, 24 Apr 2009 07:06:40 +0000</pubDate>
		<dc:creator>babaru</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://babaru.net/?p=5</guid>
		<description><![CDATA[
Flowers, originally uploaded by babaru.
]]></description>
			<content:encoded><![CDATA[<div style="text-align: left; padding: 3px;"><a title="photo sharing" href="http://www.flickr.com/photos/babaru/2835578333/"><img style="border: solid 2px #000000;" src="http://farm4.static.flickr.com/3232/2835578333_3d7b3cda94.jpg" alt="" /></a></p>
<p><span style="font-size: 0.8em; margin-top: 0px;"><a href="http://www.flickr.com/photos/babaru/2835578333/">Flowers</a>, originally uploaded by <a href="http://www.flickr.com/people/babaru/">babaru</a>.</span></div>
]]></content:encoded>
			<wfw:commentRss>http://babaru.net/archives/5/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
