反序列化没有默认构造函数的类型的 STL 容器

Posted

技术标签:

【中文标题】反序列化没有默认构造函数的类型的 STL 容器【英文标题】:Deserializing STL container of type with no default constructor 【发布时间】:2016-03-01 20:03:01 【问题描述】:

我最近学习了反序列化构造函数 (Deserializing constructor doesn't read data correctly) 的模式,以便对没有默认构造函数的类型使用序列化。现在我正在尝试序列化这些对象的 STL 容器,如下例所示:

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

#include <fstream>

class Point

public:
    Point(double x) : mX(x) 

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

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

    double mX;
;

int main()

    std::vector<Point> pointVector;
    pointVector.push_back(Point(1));
    pointVector.push_back(Point(2));

    std::ofstream outputStream("test.txt");
    boost::archive::text_oarchive outputArchive(outputStream);

    outputArchive << pointVector;
    outputStream.close();

    std::vector<Point> readPointVector;
    std::ifstream inputStream("test.txt");
    boost::archive::text_iarchive inputArchive(inputStream);
    inputArchive >> readPointVector; // Compiler error - no matching function call to Point::Point()

    return 0;

这似乎很明显,这不应该起作用,但是我如何告诉存档它需要使用反序列化构造函数来构造它读取的对象,然后再将它们添加到容器中?

--------- 编辑 ----------

在唯一答案中实施建议后,此代码编译良好,但似乎没有正确反序列化。 readPointVector 的大小只有 1,但它的大小应该是 2(并且它包含的一个对象中的数据不正确):

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

#include <fstream>

class Point

public:
    Point(double x) : mX(x) 

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

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

    double mX;
;

template <typename Archive>
Archive& operator >> (Archive& archive, std::vector<Point>& points)

    points.emplace_back(archive);
    return archive;


int main()

    std::vector<Point> pointVector;
    pointVector.push_back(Point(5.6));
    pointVector.push_back(Point(7.8));

    std::cout << pointVector.size() << std::endl; // outputs 2

    
        std::ofstream outputStream("test.txt");
        boost::archive::text_oarchive outputArchive(outputStream);

        outputArchive << pointVector;
        outputStream.close();
    

    std::vector<Point> readPointVector;
    std::ifstream inputStream("test.txt");
    boost::archive::text_iarchive inputArchive(inputStream);
    inputArchive >> readPointVector;

    std::cout << readPointVector.size() << std::endl; // outputs 1 (and readPointVector[0].mX is 2, but should be 7.8)

    return 0;

【问题讨论】:

@JoachimPileborg 所以这不可能吗?在这种情况下应该怎么做? 确保该类型有默认构造函数? @JoachimPileborg, std::vector 从来没有这样工作,它不需要元素是默认可构造的。构造函数只有一次调用,移动或复制。 也可以看到boost.org/doc/libs/1_45_0/libs/serialization/doc/…? @stijn 那是指针类型。我被告知在不使用指针时不要使用它(SergeyA 的第一条评论:***.com/questions/35703958/…) 【参考方案1】:

您可以专门研究点向量:

template <typename Archive>
Archive& operator >> (Archive& archive, std::vector<Point>& points)

    points.emplace_back(archive);
    return archive;

【讨论】:

更好 - 使用emplace @Jarod42 我想我太兴奋了,它编译并接受了答案。它似乎没有做正确的事情(请参阅问题编辑中的新演示)?

以上是关于反序列化没有默认构造函数的类型的 STL 容器的主要内容,如果未能解决你的问题,请参考以下文章

注册一个没有默认构造函数的类型

为啥spring boot可以在没有默认构造函数的情况下反序列化类?

没有默认构造函数的SpringBoot反序列化

即使存在默认构造函数,也无法从 Object 值反序列化(没有基于委托或基于属性的 Creator)

在 JSON 反序列化期间没有为“System.String”类型定义无参数构造函数

STL序列式容器之list