反序列化构造函数不正确读取数据 [英] Deserializing constructor doesn't read data correctly

查看:161
本文介绍了反序列化构造函数不正确读取数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图反序列化对象没有默认构造函数。我已经看到了你可以通过归档到一个构造函数做到这一点。但是,当我做到这似乎不正确读取数据?下面是一个例子 - 作品()输出1 2,因为它应该(使用默认的构造和操作>>),但 DoesntWork( )输出0。我踩通过,一切似乎变得适当调用。谁能解释这两个函数的区别?

 的#include<&的fstream GT;#包括LT&;升压/存档/ text_oarchive.hpp>
#包括LT&;升压/存档/ text_iarchive.hpp>
#包括LT&;升压/系列化/ serialization.hpp>类Point
{
私人的:
    友元类的boost ::系列化::访问;    模板<类TArchive>
    无效连载(TArchive&安培;归档,const的无符号整型版)
    {
        归档和放大器; MX;
        归档和放大器;我的;
    }上市:
    模板<类TArchive>
    点(TArchive&安培;存档)
    {
        序列化(存档,0);
    }    点(){} //仅提供给测试厂()    点(const的浮点X,常量浮动Y):MX(X),我(Y){}    浮MX = 4;
    浮动我= 5;
};无效作品()
{
    性病::法院LT&;< 工程():<<的std :: ENDL;
    点p(1,2);    的std ::的ofstream的OutputStream(test.archive);
    提高::档案:: text_oarchive的outputArchive(OutputStream中);
    outputArchive<<磷;
    outputStream.close();    //从文本阅读存档
    性病:: ifstream的InputStream的(test.archive);
    提高::档案:: text_iarchive inputArchive(InputStream的);
    点pointRead;
    inputArchive>> pointRead;    性病::法院LT&;< pointRead.mX<< << pointRead.mY<<的std :: ENDL;
}无效DoesntWork()
{
    性病::法院LT&;< DoesntWork():&所述;&下;的std :: ENDL;
    点p(1,2);    的std ::的ofstream的OutputStream(test.archive);
    提高::档案:: text_oarchive的outputArchive(OutputStream中);
    outputArchive<<磷;
    outputStream.close();    性病:: ifstream的InputStream的(test.archive);
    提高::档案:: text_iarchive inputArchive(InputStream的);
    点pointRead(inputArchive);    性病::法院LT&;< pointRead.mX<< << pointRead.mY<<的std :: ENDL;
}诠释的main()
{
    作品(); //输出1 2
    DoesntWork(); //输出0
    返回0;
}


解决方案

您应该不叫连载方法直接:运营商的GT;> 的存档做的办法的不仅仅是打电话连载更多;根据档案的种类它首先需要,或检查里面有什么test.archive加载preamble等,您可以通过使用调试器逐句通过验证这一点,它是一样的东西。

  22 ::系列化存档12 0 0 1.000000000e + 000 2.000000000e + 000

所以构造之后立即 text_iarchive 前两个电话给运营商和放大器; 将碰巧看到那些2 0 的在那里,而不是实际的数据。

您的构造应该是:

 模板<类TArchive>
点(TArchive&安培;存档)
{
  归档>> *这个;
}

修改这里是如何使用SFINAE以确保拷贝构造函数仍然可以调用一个例子

 点(常量点和放大器; RH):
  MX(rh.mX)
  我(rh.mY)
{
}模板<类TArchive>
点(TArchive&安培;存档,
       的std :: enable_if_t< !的std :: is_same< TArchive,点> ::值> * = nullptr)
{
  归档>> *这个;
}

I am trying to deserialize an object that does not have a default constructor. I've seen that you can do this by passing an archive to a constructor. However, when I do this it does not seem to read the data correctly? Here is an example - Works() outputs "1 2" as it should (using a default constructor and the operator>>), but DoesntWork() outputs "0 0". I've stepped through and everything seems to be getting called appropriately. Can anyone explain the difference between these two functions?

#include <fstream>

#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/serialization.hpp>

class Point
{
private:
    friend class boost::serialization::access;

    template<class TArchive>
    void serialize(TArchive& archive, const unsigned int version)
    {
        archive & mX;
        archive & mY;
    }

public:
    template<class TArchive>
    Point(TArchive& archive)
    {
        serialize(archive, 0);
    }

    Point(){} // Only provided to test Works()

    Point(const float x, const float y) : mX(x), mY(y) { }

    float mX = 4;
    float mY = 5;
};

void Works()
{
    std::cout << "Works():" << std::endl;
    Point p(1,2);

    std::ofstream outputStream("test.archive");
    boost::archive::text_oarchive outputArchive(outputStream);
    outputArchive << p;
    outputStream.close();

    // read from a text archive
    std::ifstream inputStream("test.archive");
    boost::archive::text_iarchive inputArchive(inputStream);
    Point pointRead;
    inputArchive >> pointRead;

    std::cout << pointRead.mX << " " << pointRead.mY << std::endl;
}

void DoesntWork()
{
    std::cout << "DoesntWork():" << std::endl;
    Point p(1,2);

    std::ofstream outputStream("test.archive");
    boost::archive::text_oarchive outputArchive(outputStream);
    outputArchive << p;
    outputStream.close();

    std::ifstream inputStream("test.archive");
    boost::archive::text_iarchive inputArchive(inputStream);
    Point pointRead(inputArchive);

    std::cout << pointRead.mX << " " << pointRead.mY << std::endl;
}

int main()
{
    Works(); // Output "1 2"
    DoesntWork(); // Output "0 0"
    return 0;
}

解决方案

You shouldn't call serialize methods directly: operator >> for an archive does way more than just calling serialize; depending on the type of archive it first needs to load a preamble etc. You can verify this by stepping through with the debugger, or by checking what's inside test.archive, it is something like

22 serialization::archive 12 0 0 1.000000000e+000 2.000000000e+000

so right after constructing a text_iarchive the first two calls to operator & will happen to see those 2 0's in there instead of the actual data.

Your constructor should be:

template<class TArchive>
Point(TArchive& archive)
{
  archive >> *this;
}

Edit here's an example of how to use SFINAE to make sure the copy constructor can still be invoked

Point( const Point& rh ) :
  mX( rh.mX ),
  mY( rh.mY )
{
}

template<class TArchive>
Point( TArchive& archive,
       std::enable_if_t< !std::is_same< TArchive, Point >::value >* = nullptr )
{
  archive >> *this;
}

这篇关于反序列化构造函数不正确读取数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆