使用 boost::serialization,序列化包含可变成员中的缓存派生值的对象的“最佳”方法是什么?
class Example
{
public:
Example(float n) :
num(n),
sqrt_num(-1.0)
{}
// compute and cache sqrt on first read
float get_sqrt() const
{
if(sqrt_num < 0)
sqrt_num = sqrt(num);
return sqrt_num;
}
template <class Archive>
void serialize(Archive& ar, unsigned int version)
{ ... }
private:
float num;
mutable float sqrt_num;
};
出于维护原因,我想避免将 serialize() 拆分为单独的 save() 和 load() 方法。
序列化的一个次优实现:
template <class Archive>
void serialize(Archive& ar, unsigned int version)
{
ar & num;
sqrt_num = -1.0;
}
这处理了反序列化的情况,但在序列化的情况下,缓存的值被杀死并且必须重新计算。
在这种情况下,最佳做法是什么?
最佳答案
拆分保存和加载方法并不意味着您必须维护序列化代码的两个拷贝。您可以拆分它们,然后使用通用功能将它们重新连接起来。
private:
friend class boost::serialization::access;
BOOST_SERIALIZATION_SPLIT_MEMBER()
template <class Archive>
void save(Archive& ar, const unsigned int version) const {
const_cast<Example*>(this)->common_serialize(ar, version);
}
template <class Archive>
void load(Archive& ar, const unsigned int version) {
common_serialize(ar, version);
sqrt_num = -1;
}
template <class Archive>
void common_serialize(Archive& ar, const unsigned int version) {
ar & num;
}
您可能注意到了 const_cast
。这是对这个想法的不幸警告。虽然 serialize
成员函数对于保存操作是非常量的,但是 save
成员函数需要是 const。不过,只要您正在序列化的对象最初不是声明为 const,就可以安全地将其丢弃,如上所示。文档 briefly mentions the need to cast for const members ;这是相似的。
通过上述更改,您的代码将为 ex1
和 ex2
正确打印“2”,并且您只需维护一份序列化代码。 load
代码只包含重新初始化对象内部缓存的代码; save
函数不触及缓存。
关于c++ - boost::序列化可变成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2853901/