0

0

c++中如何将结构体序列化_c++对象转换为二进制流方法

冰火之心

冰火之心

发布时间:2026-01-17 14:46:02

|

596人浏览过

|

来源于php中文网

原创

不安全,仅当结构体满足 std::is_trivially_copyable_v 时才可 memcpy;含虚函数、非平凡成员、std::string、指针、对齐差异或跨平台时均会出错。

c++中如何将结构体序列化_c++对象转换为二进制流方法

直接 memcpy 结构体是否安全?

多数情况下不安全。只有当结构体满足 std::is_trivially_copyable_v 时,memcpy 才能正确序列化。常见破坏条件包括:含虚函数、非平凡构造/析构函数、含 std::string / std::vector 等非 POD 成员、有字节对齐差异(如跨平台传输)、或含指针成员(只拷贝地址,不拷贝所指数据)。

验证方式:

static_assert(std::is_trivially_copyable_v, "MyStruct is not trivially copyable");
  • 若断言失败,说明不能用 memcpy 直接转二进制流
  • 即使本地运行正常,跨编译器或跨平台(如 x86_64 ↔ ARM64)也可能因 padding、endianness 或 ABI 差异出错
  • 调试时容易误判——“看起来能读出来” ≠ “语义正确”

含 std::string 或容器的结构体怎么序列化?

必须手动序列化每个字段,不能整体 memcpy。核心思路是:先写长度,再写内容;对嵌套对象递归处理。

例如:

立即学习C++免费学习笔记(深入)”;

白瓜AI
白瓜AI

白瓜AI,一个免费图文AI创作工具,支持 AI 仿写,图文生成,敏感词检测,图片去水印等等。

下载
struct Person {
    int id;
    std::string name;
    std::vector scores;
};

std::vector serialize(const Person& p) {
    std::vector buf;
    // 写 id(4 字节)
    buf.insert(buf.end(), reinterpret_cast(&p.id), 
               reinterpret_cast(&p.id) + sizeof(p.id));
    // 写 name 长度 + 数据
    uint32_t len = static_cast(p.name.size());
    buf.insert(buf.end(), reinterpret_cast(&len), 
               reinterpret_cast(&len) + sizeof(len));
    buf.insert(buf.end(), p.name.begin(), p.name.end());
    // 写 scores 大小和元素
    len = static_cast(p.scores.size());
    buf.insert(buf.end(), reinterpret_cast(&len), 
               reinterpret_cast(&len) + sizeof(len));
    for (double d : p.scores) {
        buf.insert(buf.end(), reinterpret_cast(&d), 
                   reinterpret_cast(&d) + sizeof(d));
    }
    return buf;
}
  • 注意 std::string::data() 不保证以 \0 结尾,所以必须显式存长度
  • 浮点数直接按位拷贝可跨平台(IEEE 754),但需统一 endianness(建议网络字节序,用 htons/htonl
  • 未处理异常(如内存分配失败)或版本兼容性(后续加字段怎么办)

用 boost::serialization 还是 cereal?

cereal 更轻量、头文件即用、无运行时开销,适合嵌入式或性能敏感场景;boost::serialization 功能全但依赖大、编译慢、二进制格式不兼容旧版。

cereal 的典型写法:

#include 
#include 
#include 

struct Person {
    int id;
    std::string name;
    std::vector scores;

    template 
    void serialize(Archive& ar) {
        ar(CEREAL_NVP(id), CEREAL_NVP(name), CEREAL_NVP(scores));
    }
};

// 序列化
std::ostringstream os;
cereal::BinaryOutputArchive oarchive(os);
oarchive(person);

std::vector bin = os.str(); // 获取二进制流
  • 必须为每个可序列化类型提供 serialize 成员函数或非成员特化
  • cereal 默认不处理多态(需额外宏),也不支持直接指针序列化(会报错)
  • 生成的二进制不是自描述的——反序列化端必须用完全相同的 struct 定义和 cereal 版本

跨平台传输时最容易忽略的三个点

哪怕结构体是 trivially copyable,跨平台仍可能失败:

  • intlong 在不同平台宽度不同(Linux x86_64 中 long 是 8 字节,Windows 是 4 字节),应改用 int32_t / uint64_t 等固定宽度类型
  • 大小端不一致:x86 是小端,ARM 可配,网络协议通常要求大端;建议所有整数字段在序列化前调用 htons / htonl / htobe64
  • 结构体 padding 差异:同一定义在 GCC 和 MSVC 下可能因默认对齐策略不同而 layout 不同;用 #pragma pack(1)[[gnu::packed]] 强制紧凑,但要确认目标平台支持未对齐访问(否则 SIGBUS)

真正可靠的序列化,从来不是“把内存 dump 出来”,而是明确定义字段顺序、编码规则和边界行为。哪怕只是两个进程间通信,也值得花十分钟写个 serialize() / deserialize() 对。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

317

2023.08.02

java多态详细介绍
java多态详细介绍

本专题整合了java多态相关内容,阅读专题下面的文章了解更多详细内容。

15

2025.11.27

golang结构体相关大全
golang结构体相关大全

本专题整合了golang结构体相关大全,想了解更多内容,请阅读专题下面的文章。

196

2025.06.09

golang结构体方法
golang结构体方法

本专题整合了golang结构体相关内容,请阅读专题下面的文章了解更多。

189

2025.07.04

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

317

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

538

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

52

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

197

2025.08.29

高德地图升级方法汇总
高德地图升级方法汇总

本专题整合了高德地图升级相关教程,阅读专题下面的文章了解更多详细内容。

27

2026.01.16

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL 教程
PostgreSQL 教程

共48课时 | 7.3万人学习

Git 教程
Git 教程

共21课时 | 2.7万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号