gpt4 book ai didi

c++ - boost 处理可能的空指针的类的序列化

转载 作者:行者123 更新时间:2023-11-30 05:40:13 26 4
gpt4 key购买 nike

我想序列化下面的类,它包装了一个可以处理空 m_element 的指针,正如您在调用默认构造函数时看到的那样。这遵循这个 question .

Live MCVE on Coliru

template <typename T>
struct Ptr { // Ptr could use init constructor here but this is not the point
Ptr() { m_elem = 0; }
Ptr(const T* elem) {
if (elem)
m_elem = new T(*elem);
else
m_elem = 0;
}
Ptr(const T& elem)
{
m_elem = new T(elem);
}
Ptr(const Ptr& elem)
{
if (elem.m_elem)
m_elem = new T(*(elem.m_elem));
else
m_elem = 0;
}
virtual ~Ptr() { delete m_elem; m_elem = 0; };

const T& operator*() const { return *m_elem; };
T& operator*() { return *m_elem; };

const T* operator->() const { return m_elem; };
T* operator->() { return m_elem; };

T* m_elem;
};

namespace boost { namespace serialization {

// Not sure about the approach to manage null m_elem here
template<class Archive, class T>
void save(Archive & ar, const Ptr<T> &ptr, const unsigned int version)
{
T elem = 0;
if (ptr.m_elem != 0)
ar& boost::serialization::make_nvp("data", *ptr.m_elem);
else
ar& boost::serialization::make_nvp("data", elem);
}

// How to implement load ?
template<class Archive, class T>
void load(Archive & ar, Ptr<T> &ptr, const unsigned int version)
{
ar& boost::serialization::make_nvp("data", *ptr.m_elem);
}

template<class Archive, class T>
void serialize(Archive & ar, Ptr<T> &ptr, const unsigned int version)
{
boost::serialization::split_free(ar, ptr, version);
}

}} // end namespace


int main()
{
{
Ptr<A> p;
std::ostringstream oss;
boost::archive::xml_oarchive oa(oss);
oa << BOOST_SERIALIZATION_NVP(p);
std::cout << oss.str() << std::endl;

// segfault

Ptr<double> po;
std::istringstream iss;
iss.str(oss.str());
boost::archive::xml_iarchive ia(iss);
ia >> BOOST_SERIALIZATION_NVP(po);

}
{
Ptr<double> p(new double(2.0));
std::cout << *(p.m_elem) << std::endl;

std::ostringstream oss;
boost::archive::xml_oarchive oa(oss);
oa << BOOST_SERIALIZATION_NVP(p);
std::cout << oss.str() << std::endl;

// segfault

Ptr<double> po;
std::istringstream iss;
iss.str(oss.str());
boost::archive::xml_iarchive ia(iss);
ia >> BOOST_SERIALIZATION_NVP(po);

}
}

序列化似乎有效,但反序列化给出了一个段错误。我在 C++0x 中工作。

  • 如果可能,我如何在不更改 Ptr 的情况下提供安全的保存和加载函数来序列化 Ptr?
  • 如果我需要修改 Ptr,你有什么建议?

编辑:感谢 Jarod42 的评论,我想出了以下使用 bool 值检测空指针的保存/加载函数。现在,当 m_elem 为 null 时,我不再有段错误,但当它不为 null 时,我有一个。

template<class Archive, class T>
void save(Archive & ar, const Ptr<T> &ptr, const unsigned int version)
{
bool is_null;
if (ptr.m_elem != 0) {
is_null = false;
ar& boost::serialization::make_nvp("is_null", is_null);
ar& boost::serialization::make_nvp("data", *ptr.m_elem);
}
else
{
is_null = true;
ar& boost::serialization::make_nvp("is_null", is_null);
}
}

template<class Archive, class T>
void load(Archive & ar, Ptr<T> &ptr, const unsigned int version)
{
bool is_null;
ar& boost::serialization::make_nvp("is_null", is_null);
if (is_null == true) {
ptr.m_elem = 0;
}
else
{
ar& boost::serialization::make_nvp("data", *ptr.m_elem);
}
}

最佳答案

boost::archive 的保存和加载方法理解指针和对象引用之间的区别。您不需要指定 *m_elem。 m_elem 可以(并且可以正常工作)。 Boost 将理解指针是否为空,并且将简单地存储一个指示空指针的值,该值将被正确反序列化。

(简化)示例:

#include <vector>
#include <string>
#include <iostream>
#include <sstream>
#include <algorithm>
#include <iterator>

#include <boost/archive/xml_iarchive.hpp>
#include <boost/archive/xml_oarchive.hpp>
#include <boost/serialization/access.hpp>
#include <boost/serialization/nvp.hpp>
#include <boost/serialization/split_free.hpp>

struct A {
A() : a(0) {}
A(int aa) : a(aa) {}
int a;
template <class Archive>
void serialize(Archive& ar, const unsigned int /*version*/)
{
ar& BOOST_SERIALIZATION_NVP(a);
}
};

std::ostream& operator<<(std::ostream& os, const A& a) {
os << "A{" << a.a << "}";
return os;
}

template <typename T>
struct Ptr { // Ptr could use init constructor here but this is not the point
Ptr()
: m_elem(0)
{}

Ptr(T elem)
: m_elem(new T(elem))
{
}

private:
// no copies
Ptr(const Ptr&);
Ptr& operator=(const Ptr&);
public:
// delete is a NOP when called with nullptr arg
virtual ~Ptr() { delete m_elem; };

T* get() const {
return m_elem;
}

T& operator*() const {
return *m_elem;
}

template <class Archive>
void serialize(Archive& ar, const unsigned int /*version*/)
{
ar& BOOST_SERIALIZATION_NVP(m_elem);
}

private:
T* m_elem;
};

template<class T>
std::ostream& operator<<(std::ostream& os, const Ptr<T>& p) {
if (p.get()) {
os << *p;
}
else {
os << "{nullptr}";
}
return os;
}

int main()
{
std::string payload;

{
Ptr<A> p;
std::cout << p << std::endl;
std::ostringstream oss;
boost::archive::xml_oarchive oa(oss);
oa << BOOST_SERIALIZATION_NVP(p);
payload = oss.str();
// std::cout << payload << std::endl;

Ptr<A> p2(A(6));
std::cout << p2 << std::endl;
oa << BOOST_SERIALIZATION_NVP(p2);
payload = oss.str();
// std::cout << payload << std::endl;
}
{

Ptr<A> po;
std::istringstream iss(payload);
boost::archive::xml_iarchive ia(iss);
ia >> BOOST_SERIALIZATION_NVP(po);
std::cout << po << std::endl;

Ptr<A> po2;
ia >> BOOST_SERIALIZATION_NVP(po2);
std::cout << po2 << std::endl;
}
}

预期输出:

{nullptr}
A{6}
{nullptr}
A{6}

关于c++ - boost 处理可能的空指针的类的序列化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31809638/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com