Boost的Serialization和SmartPoint搭配使用

         准确来说,这篇博文并不是译文,而是一篇某个网页中代码改写而来。原文章中的代码存在几处严重错误,网页又不提供留言功能(不是没有而是一个没有留言功能的留言板)。4年过去了,作者对这些错误不更正让人无法接受。遂在此“翻译”之。原网址:点击打开链接


        此代码是用来解决Boost库中持久化内存问题(主要是内存泄露)。代码如下:

#include <fstream>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <cstdlib>
#include <boost/tr1/memory.hpp>
#include <vector>
#include <map>
#include <boost/tr1/unordered_map.hpp>
#include <memory>
#include <boost/serialization/shared_ptr.hpp>
#include <boost/serialization/split_free.hpp>

using namespace std;
using namespace boost::serialization;

namespace boost
{
    namespace serialization
	{
		//implement serialization for auto_ptr<T>
		//note: this must be added to the boost namesapce in order to
		//be called by the libary
		template< typename Archive, typename T>
		inline void save( Archive &ar, const std::auto_ptr<T> &t, const unsigned int file_version)
		{
			//only the raw pointer has to be saved
			cont T *const tx = t->get();
			ar << tx;
		}

		template <typename Archive, typename T>
		inline void load(Archive &ar, std::auto_ptr<T> &t, const unsigned int file_version)
		{
			T *pTarget;
			ar >> pTarget;  
			//note that the reset automagically maintains the reference count
#if BOOST_WORKAROUND (BOOST_DINKUMWARE_STDLIB, ==1)
			t->release();
			t = std::auto_ptr<T>(pTarget);
#else
			t->reset(pTarget);
#endif
		}
		//split non-instrusive serialization function member into sparate
		//non intrusive asve/load member functions
		template<typename Archive, typename T>
		inline void serialize(Archive &ar, std::auto_ptr<T> &t, const unsigned int file_version)
		{
			boost::serialization::split_free(ar, t, file_version);
		}
	}// namespace serialization
}//namespace boost

//举例说明简单类型的序列化
class gps_position
{
private:
	friend class boost::serialization::access;

	template<typename Archive>
	void serialize(Archive &ar, const unsigned int version)
	{
		ar & degrees;
		ar & minutes;
		ar & seconds;
	}
	int degrees;
	int minutes;
	float seconds;
public:
	gps_position()
	{
		degrees = 0;
		minutes = 0;
		seconds = 0.0f;
	}
	gps_position(int d, int m, float s):
	     degrees(d),minutes(m),seconds(s) { }
}; 

class bus_stop
{
	friend class boost::serialization::access;
	template <typename Archive>
	void serialize( Archive &ar, const unsigned int version )
	{
		ar & latitude;
		ar & longitude;
	}
	gps_position latitude;
	gps_position longitude;
public:
	bus_stop()  {  }
	bus_stop(const gps_position &lat_, const gps_position &long_):
	     latitude(lat_), longitude(long_)  {   }
	virtual ~bus_stop()  {   }
};

class bus_stop_corner:public bus_stop
{
	friend class boost::serialization::access;
	template<class Archive>
	void serialize(Archive & ar, const unsigned int version)
	{
		// 序列化基类信息
		ar & boost::serialization::base_object<bus_stop>(*this);
		ar & street1;
		ar & street2;
	}
	std::string street1;
	std::string street2;

public:
	bus_stop_corner() {   }
	bus_stop_corner(const gps_position & lat_, const gps_position & long_,
		            const std::string & s1_, const std::string & s2_) :
	                     bus_stop(lat_, long_), street1(s1_), street2(s2_) {    }

	virtual std::string description() const
	{
		return street1 + " and " + street2;
	}
	~bus_stop_corner() {  }
};

class bus_route
{
	friend class boost::serialization::access;
    //相对于BoostLearn03,此处改写是为了减少代码量并显示更清楚
	boost::shared_ptr<bus_stop_corner> msptrBusStop;
	boost::shared_ptr<bus_stop_corner> maptrBusStop;

	template<class Archive>
	void serialize(Archive & ar, const unsigned int version)
	{
		ar & msptrBusStop;
		ar & maptrBusStop;
	}
public:
	bus_route(bus_stop_corner *apStop1, bus_stop_corner *apStop2)
		:msptrBusStop(apStop1/*new bus_stop_corner(apStop1)*/),
		 maptrBusStop(apStop2/*new bus_stop_corner(apStop2)*/)
	{

	}
	bus_route()  
	{

	}
	~bus_route()
	{
		
	}
};

int main(void)
{
		std::ofstream ofs("bus_route");
	//创建类实例
	const gps_position latitude(1, 2, 3.3f);
	const gps_position longitude(4, 5, 6.6f);

        //注解1:
	bus_stop_corner *lpStop1 = new bus_stop_corner(latitude, longitude, "corn1", "corn2");
	bus_stop_corner *lpStop2 = new bus_stop_corner(latitude, longitude, "corn3", "corn4");

        //注解2:
	bus_route route(lpStop1, lpStop2);

	{
		boost::archive::text_oarchive oa(ofs);
		oa << route;
	}

	bus_route new_route;
	{
		std::ifstream ifs("bus_route", std::ios::binary);
		boost::archive::text_iarchive ia(ifs);
		ia >> new_route;
	}
	//当智能指针的引用计数为0时,内存会被释放.
	return 0;
}


在修改原来的代码是发现一个弄不明白的地方,如进行下面的更改后便出现 “Expression:_BLOCK_TYPE_IS_VALID (pHead->nBlockUse)”错误.

1.代码中"注解①"处若换成如下两行代码

    bus_stop_corner lpStop1 (latitude, longitude, "corn1", "corn2");
    bus_stop_corner lpStop2 (latitude, longitude, "corn3", "corn4");

2."注解②"处换成
bus_route route(&lpStop1, &lpStop2);

3.运行时出现"“Expression:_BLOCK_TYPE_IS_VALID (pHead->nBlockUse)”错误".

        为什么出现如此现象我也不能可定。猜测:

         对比发现,一个是构造函数构造出来的,另一个是用new运算符分配的内存。构造函数构造对象时分配的内存由析构函数负责完成内存释放,new运算符分配的内存通过delete运算或是通过智能指针的引用计数来释放。

        这个猜测还需验证,现记录在此,以后有能力证明这个猜测再来完善。 2013-11-15


更新

2015-04-21      第一次更新

         上面1,2,3的疑惑根源在class bus_route类中使用了shared_ptr引用计数智能指针,其中msptrBusStop、maptrBusStop属性都属于shared_ptr智能指针。shared_ptr智能指针智能封装由new分配出来的指针,所以使用构造函数生成的对象用bus_route route(&lpStop1, &lpStop2);传入由shared_ptr进行封装是不允许的。所以出现以上的疑惑之处。

        对于C++智能指针的详细解析可以参看C++智能指针使用总结文章。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值