反序列化构造函数无法正确读取数据
我正在尝试反序列化一个没有默认构造函数的对象.我已经看到您可以通过将存档传递给构造函数来做到这一点.但是,当我这样做时,它似乎没有正确读取数据?这是一个示例 - Works()
输出1 2",因为它应该(使用默认构造函数和运算符>>),但 DoesntWork()
输出0 0".我已经通过了,一切似乎都得到了适当的调用.谁能解释一下这两个函数的区别?
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;
}
推荐答案
你不应该直接调用 serialize
方法:operator >>
for a archive do way 不仅仅是调用 serialize
;根据存档的类型,它首先需要加载前导码等.您可以通过调试器逐步执行或检查 test.archive 中的内容来验证这一点,就像
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
所以在构造一个 text_iarchive
之后,对 operator &
的前两次调用会碰巧看到那些 2 0
在那里实际数据.
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.
你的构造函数应该是:
template<class TArchive>
Point(TArchive& archive)
{
archive >> *this;
}
编辑这里是如何使用 SFINAE 确保仍然可以调用复制构造函数的示例
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;
}
相关文章