我正在尝试提升:: serialize结构,这些结构指向对象(比如符号类),实现单实例每个唯一的概念< something>。这意味着,这些对象不是直接创建的,而是使用静态方法符号:: get()。此方法从某个全局字典中检索现有对象,或者在必要时创建新对象。
现在困难的是,在我的系统中,我有许多大型结构,指向这些符号。结构不能同时适合所有内存。所以我需要分别按顺序构建,预处理和序列化每个结构。稍后我会根据请求反序列化和处理结构。
标准的boost :: serialize方法,即load(...)和save(...)在这里不起作用。结构的Uppon反序列化将失去符号的系统范围的唯一性,并且序列化将浪费大量空间(我的符号对象非常大)。我已经阅读了boost文档,发现对于非标准构造函数,我可以使用save_construct_data和load_construct_data函数。但文档也说,默认的load_construct_data“只使用默认构造函数初始化以前分配的内存”。所以这不是它。
问题是:如何绕过这个加载函数,以便我可以避免任何分配并使用我的符号:: get()代替?或者也许有更优雅的解决方案?
编辑:附上一个简单的代码来证明问题。
struct structure_element {
};
class symbol : public structure_element {
symbol(string x);
map<string, symbol> known_symbols;
public:
static symbol *get(string x) {
if (known_symbols.find(x) != known.symbols.end()){
known_symbols[x] = symbol(x);
}
return &known_symbols[x];
}
}
class structure_node : public structure_element {
set<symbol *> some_attributes;
vector<structure_element *> children;
}
答案 0 :(得分:0)
一般情况下,特殊情况可以实施 load_construct_data
(显然这意味着您不要依赖于您在问题中已经观察到的默认实现。)
更具体地说:使用Boost Flyweight。或者看看他们如何implemented serialization获得灵感。
如果没有具体的示例程序,我无法为您演示。
填写一些空白,这是一个应该给人一种感觉的演示程序:
#include <iostream>
#include <boost/archive/text_oarchive.hpp>
#include <boost/serialization/string.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/set.hpp>
#include <boost/serialization/map.hpp>
#if 0
# define DEMO_FLYWEIGHT
# include <boost/flyweight/serialize.hpp>
# include <boost/flyweight.hpp>
#endif
struct structure_element {
virtual ~structure_element() {}
private:
friend class boost::serialization::access;
template <typename Ar> void serialize(Ar& /*ar*/, unsigned /*version*/) {
}
};
namespace detail {
struct symbol_impl {
symbol_impl(std::string const& x) : _x(x) { }
#ifdef DEMO_FLYWEIGHT
size_t hash() const { return boost::hash_value(_x); }
//bool operator< (symbol_impl const& other) const { return _x < other._x; }
bool operator==(symbol_impl const& other) const { return _x == other._x; }
#endif
private:
std::string _x;
friend class boost::serialization::access;
template <typename Ar> void serialize(Ar& ar, unsigned /*version*/) {
ar & _x;
}
};
}
#ifdef DEMO_FLYWEIGHT
namespace boost {
template <> struct hash<::detail::symbol_impl> {
size_t operator()(::detail::symbol_impl const& s) const { return s.hash(); }
};
}
#endif
struct symbol : public structure_element {
symbol(std::string const& x) : _impl(x) {}
private:
#ifdef DEMO_FLYWEIGHT
boost::flyweight<detail::symbol_impl> _impl;
#else
detail::symbol_impl _impl;
#endif
friend class boost::serialization::access;
template <typename Ar> void serialize(Ar& ar, unsigned /*version*/) {
ar & boost::serialization::base_object<structure_element>(*this);
ar & _impl;
}
};
struct structure_node : public structure_element {
structure_node(std::set<symbol*> a, std::vector<structure_element*> c)
: some_attributes(std::move(a)), children(std::move(c))
{
}
// TODO value semantics/ownership
private:
std::set<symbol *> some_attributes;
std::vector<structure_element *> children;
friend class boost::serialization::access;
template <typename Ar> void serialize(Ar& ar, unsigned /*version*/) {
ar & boost::serialization::base_object<structure_element>(*this);
ar & some_attributes;
ar & children;
}
};
#include <boost/make_shared.hpp>
int main() {
// everything is leaked, by design
symbol* bar = new symbol("bar");
structure_node data {
{
new symbol("foo"),
bar,
new symbol("foo"),
new symbol("foo"),
bar,
},
{
bar,
}
};
boost::archive::text_oarchive oa(std::cout);
oa << data;
}
注意:
Live On Coliru 没有 flyweight
22 serialization::archive 11 0 0 1 0
0 0 0 4 0 3 1 0
1
2 0 0 3 bar 3
3
4 3 foo 3
5
6 3 foo 3
7
8 3 foo 0 0 1 0 3 1
Live On Coliru 启用了flyweight
22 serialization::archive 11 0 0 1 0
0 0 0 4 0 3 1 0
1
2 0 0 0 0 0 3 bar 3
3
4 1 3 foo 3
5
6 1 3
7
8 1 0 0 1 0 3 1
注意在通过指针序列化时如何跟踪对象。这意味着即使不使用flyweight也没有序列化重复序列,例如, bar
对象被使用了3次。
对于foo
对象,您可以看到它的实现是&#34;重复数据删除&#34;如果你在使用flyweight时会。
Boost Flyweight具有高度可配置性,可以使其性能明显优于默认值。如果您想了解更多信息,请参阅图书馆文档