提升序列化如何实际保存 const 对象
How does boost serialization actually save const object
考虑下面的序列化示例,当此数据是常量且序列化函数不是常量函数时,boost如何应对保存数据?
某处有常量投射吗?
struct Settings
{
Settings();
uint32_t buffers_size;
uint32_t messages;
};
template < class Archive >
void serialize(Archive& ar, Settings& settings, unsigned int /*version*/)
{
using boost::serialization::make_nvp;
ar
& make_nvp< uint32_t >("buffers_size", settings.buffers_size )
& make_nvp< uint32_t >("messages", settings.messages);
}
据我所知,在保存对象之前,常常性确实被抛弃了。我认为相关代码在oserializer.hpp
:
template<class Archive, class T>
BOOST_DLLEXPORT void oserializer<Archive, T>::save_object_data(
basic_oarchive & ar,
const void *x
) const {
// make sure call is routed through the highest interface that might
// be specialized by the user.
BOOST_STATIC_ASSERT(boost::is_const< T >::value == false);
boost::serialization::serialize_adl(
boost::serialization::smart_cast_reference<Archive &>(ar),
* static_cast<T *>(const_cast<void *>(x)),
version()
);
}
在调用此方法之前,序列化的对象引用将转换为const void *
,对应于此处的第二个参数。此指针的恒常性被强制转换,生成的指针被强制转换为相应的指针类型,然后取消引用该指针类型。
这就提出了在尝试序列化const
对象时调用未定义行为的可能性的问题:如果 serialize
member/free 函数以某种方式修改了对象,那么创建一个 const
对象并将其保存到存档将是未定义的行为,并且在编译时不会被注意到!
如果将函数拆分为 save
和 load
,则必须save
标记为 const
,以防止意外修改对象。