提升矢量序列化追加问题

boost vector serialization append issue

考虑以下示例:

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


#include <iostream>
#include <sstream>

using namespace boost;
using namespace std;


int main()
{
    std::ostringstream oss;
    boost::archive::text_oarchive oa(oss);



    vector<int> src1 = {1}, src2 = {2};

    vector<int> dst;

    oa << src1;
    oa << src2;

    string serialized = oss.str();
    std::istringstream iss(serialized);
    boost::archive::text_iarchive ia(iss);


    ia >> dst;

    cout << "size=" << dst.size() << endl;

    ia >> dst;
    cout << "size=" << dst.size() << endl;
}

输出:
尺寸=1
尺寸=1

一切都很好。但是,如果将 vector 更改为 vector:

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


#include <iostream>
#include <sstream>

using namespace boost;
using namespace std;


int main()
{
    std::ostringstream oss;
    boost::archive::text_oarchive oa(oss);


    vector<string> src1 = {"hi"}, src2 = {"hi"};

    vector<string> dst;


    oa << src1;
    oa << src2;

    string serialized = oss.str();
    std::istringstream iss(serialized);
    boost::archive::text_iarchive ia(iss);


    ia >> dst;

    cout << "size=" << dst.size() << endl;

    ia >> dst;
    cout << "size=" << dst.size() << endl;
}

输出:
尺寸=1
尺寸=2

结果附加到 dst,未分配。为什么? "assign semantic"如何实现?

编译器:gcc 版本 5.2.1 20151010 (Ubuntu 5.2.1-22ubuntu2)
编译:g++ -std=c++11 test2.cc -lboost_serialization

在 boost 1.58 的源代码中有以下代码。

if(detail::is_default_constructible<U>()){
    t.resize(count);
    typename std::vector<U, Allocator>::iterator hint;
    hint = t.begin();
    while(count-- > 0){
        ar >> boost::serialization::make_nvp("item", *hint++);
    }
}
else{
    t.reserve(count);
    while(count-- > 0){
        detail::stack_construct<Archive, U> u(ar, item_version);
        ar >> boost::serialization::make_nvp("item", u.reference());
        t.push_back(u.reference());
        ar.reset_object_address(& t.back() , & u.reference());
     }
}

detail::is_default_constructible returns false for std::string(由于某些原因使用boost::has_trivial_constructor)和true for int.所以,当Uint时,会调用resize,然后使用赋值,但当Ustd::string时,reserve会被使用(保留实际上不调整容器的大小)然后 push_back 将被使用。

简单的解决方法是 clear 向量,然后再从存档中读取第二次。

ia >> dst;

cout << "size=" << dst.size() << endl;

dst.clear();
ia >> dst;
cout << "size=" << dst.size() << endl;