You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何序列化与反序列化C++11中的std::vector<details>结构体向量?

嘿,作为刚接触C序列化的初学者,我太懂你现在的困惑了——把内存里的std::vector<details>存到文件或者传去别的地方,再完整读回来还原,确实需要清晰易懂的步骤。下面我给你讲两种适合C11的方法,都是新手友好型的:

方法一:手动实现序列化/反序列化(无第三方库)

这种方法能让你彻底搞懂序列化的本质:就是把结构体的每个成员按固定格式写入流,再按一模一样的格式读出来还原。非常适合新手理解原理。

首先先假设你的details结构体是这样的(如果你的结构体成员不同,只要对应修改读写逻辑就行):

#include <vector>
#include <fstream>
#include <string>
#include <stdexcept>
#include <iostream>

// 你的details结构体示例
struct details {
    int id;
    std::string name;
    double value;
};

序列化函数:把向量写入文件

// 序列化:将vector<details>写入二进制文件
void serialize(const std::vector<details>& vec, const std::string& filename) {
    // 一定要用二进制模式打开文件,避免文本模式自动转换换行符导致数据错乱
    std::ofstream file(filename, std::ios::binary);
    if (!file.is_open()) {
        throw std::runtime_error("无法打开文件进行序列化");
    }

    // 先写入向量的元素个数,这样反序列化时知道要读多少个元素
    const size_t vec_size = vec.size();
    file.write(reinterpret_cast<const char*>(&vec_size), sizeof(vec_size));

    // 逐个写入每个details的成员
    for (const auto& item : vec) {
        // 写入int类型的id
        file.write(reinterpret_cast<const char*>(&item.id), sizeof(item.id));
        
        // 写入std::string:必须先写字符串长度,再写内容(直接写string对象会存内部指针,反序列化会失效)
        const size_t name_len = item.name.size();
        file.write(reinterpret_cast<const char*>(&name_len), sizeof(name_len));
        file.write(item.name.data(), name_len);
        
        // 写入double类型的value
        file.write(reinterpret_cast<const char*>(&item.value), sizeof(item.value));
    }
}

反序列化函数:从文件还原向量

// 反序列化:从二进制文件读取并还原vector<details>
std::vector<details> deserialize(const std::string& filename) {
    std::ifstream file(filename, std::ios::binary);
    if (!file.is_open()) {
        throw std::runtime_error("无法打开文件进行反序列化");
    }

    std::vector<details> result;

    // 先读取向量的元素个数
    size_t vec_size;
    file.read(reinterpret_cast<char*>(&vec_size), sizeof(vec_size));
    result.reserve(vec_size); // 提前分配空间,提升效率

    // 逐个读取并还原每个details对象
    for (size_t i = 0; i < vec_size; ++i) {
        details item;
        
        // 读取id
        file.read(reinterpret_cast<char*>(&item.id), sizeof(item.id));
        
        // 读取string:先读长度,再分配空间读取内容
        size_t name_len;
        file.read(reinterpret_cast<char*>(&name_len), sizeof(name_len));
        item.name.resize(name_len);
        file.read(&item.name[0], name_len);
        
        // 读取value
        file.read(reinterpret_cast<char*>(&item.value), sizeof(item.value));

        result.push_back(item);
    }

    return result;
}

测试用例

int main() {
    // 构造测试数据
    std::vector<details> object_details = {
        {1, "张三", 3.1415},
        {2, "李四", 2.7182},
        {3, "王五", 1.4142}
    };

    // 序列化到文件
    try {
        serialize(object_details, "details_data.dat");
        std::cout << "序列化成功!已保存到details_data.dat" << std::endl;
    } catch (const std::exception& e) {
        std::cerr << "序列化失败:" << e.what() << std::endl;
        return 1;
    }

    // 反序列化还原数据
    std::vector<details> restored_data;
    try {
        restored_data = deserialize("details_data.dat");
        std::cout << "\n反序列化成功!还原的数据如下:" << std::endl;
        for (const auto& item : restored_data) {
            std::cout << "ID: " << item.id << ", 名称: " << item.name << ", 值: " << item.value << std::endl;
        }
    } catch (const std::exception& e) {
        std::cerr << "反序列化失败:" << e.what() << std::endl;
        return 1;
    }

    return 0;
}

手动实现的注意事项

  • 必须用二进制模式打开文件,否则文本模式会自动转换\n等换行符,导致数据错位。
  • 对于std::string、std::vector这类动态容器,不能直接写入整个对象(因为它们内部存的是指针),必须先写长度再写内容。
  • 如果你的details有嵌套结构体、指针等复杂成员,需要扩展对应的读写逻辑。

方法二:使用Boost.Serialization(更适合复杂场景)

如果你的项目允许使用第三方库,Boost.Serialization是C生态里非常成熟的序列化工具,完美支持C11。它能自动处理几乎所有标准库类型(包括std::vector、std::string),不用手动写每个成员的读写逻辑,适合结构体复杂的实际项目。

步骤1:准备Boost库

你需要安装Boost库(C++11对应的Boost版本建议选1.58及以上),确保编译环境能找到Boost的头文件和库文件。

代码实现

#include <vector>
#include <fstream>
#include <string>
#include <iostream>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/string.hpp>

struct details {
    int id;
    std::string name;
    double value;

    // 必须添加这个模板化的serialize函数,Boost会通过它访问结构体成员
    template<class Archive>
    void serialize(Archive& ar, const unsigned int /*version*/) {
        ar & id;    // 序列化id
        ar & name;  // 序列化name(Boost自动处理string)
        ar & value; // 序列化value
    }
};

// 序列化函数
void serialize_with_boost(const std::vector<details>& vec, const std::string& filename) {
    std::ofstream file(filename, std::ios::binary);
    boost::archive::binary_oarchive oa(file);
    oa << vec; // 直接序列化整个vector,Boost自动处理内部的details对象
}

// 反序列化函数
std::vector<details> deserialize_with_boost(const std::string& filename) {
    std::vector<details> result;
    std::ifstream file(filename, std::ios::binary);
    boost::archive::binary_iarchive ia(file);
    ia >> result; // 直接反序列化还原vector
    return result;
}

// 测试用例和方法一类似,替换成这两个函数即可
int main() {
    std::vector<details> object_details = {
        {1, "张三", 3.1415},
        {2, "李四", 2.7182},
        {3, "王五", 1.4142}
    };

    try {
        serialize_with_boost(object_details, "boost_details.dat");
        std::cout << "Boost序列化成功!" << std::endl;

        auto restored_data = deserialize_with_boost("boost_details.dat");
        std::cout << "\nBoost反序列化成功!还原的数据:" << std::endl;
        for (const auto& item : restored_data) {
            std::cout << "ID: " << item.id << ", 名称: " << item.name << ", 值: " << item.value << std::endl;
        }
    } catch (const std::exception& e) {
        std::cerr << "出错了:" << e.what() << std::endl;
        return 1;
    }

    return 0;
}

Boost方法的注意事项

  • 编译时需要链接Boost的serialization库,比如在GCC下编译要加参数:g++ your_code.cpp -o your_program -lboost_serialization。
  • 如果你的details有父类或者嵌套结构体,只需要给每个类都添加serialize函数即可。
  • Boost还支持文本格式、XML格式的序列化,只要替换对应的归档类(比如text_oarchive)就行。

总结

  • 如果你是新手想彻底搞懂序列化原理,先从手动实现开始,能清楚看到数据的读写过程。
  • 如果是实际项目开发,尤其是结构体复杂的情况,Boost.Serialization更高效,能减少手动写代码的出错概率。

内容的提问来源于stack exchange,提问作者2adnielsenx xx

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 04:31:52