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

如何将Data类成员的所有字节数组打包到单个vector并实现序列化反序列化

Data类序列化与反序列化问题解答

Q1:合并后的字节vector如何拆分?是否需要分隔符?

不需要额外加分隔符——因为你要序列化的每个数据类型的字节长度是固定的:

  • int32固定占4字节
  • int64固定占8字节(你代码里的示例输出是6字节,应该是笔误)
  • float固定占4字节
  • double固定占8字节

合并字节序列的方法

把各个成员的字节数据依次追加到总vector即可:

  1. 调用encode得到int32的字节序列,用vector::insert插入到总vector末尾
  2. 同理插入int64的字节序列
  3. 将float的二进制字节(通过memcpy得到的数组)逐个转成uint8_t,插入总vector
  4. 最后处理double的二进制字节,同样插入总vector

反序列化拆分的方法

按照序列化时的固定顺序,依次截取对应长度的字节段解析:

  1. 从vector起始位置取前4字节,解析为int32
  2. 接着取接下来的8字节,解析为int64
  3. 再取4字节解析float
  4. 最后取8字节解析double

Q2:更优的实现方式

核心优化方向

  1. 跨平台字节序统一:不同机器的大端/小端字节序会导致解析失败,所以encode/decode必须统一字节序(比如用网络字节序——大端),整数用htonl/ntohl、htonll/ntohll转换,浮点型也需要转成固定字节序后再序列化。
  2. 代码复用:用模板函数封装通用的序列化/反序列化逻辑,避免重复编写相似代码。
  3. 安全内存操作:用std::copy或vector::insert配合指针范围代替手动memcpy,减少出错概率。
  4. 减少拷贝开销:反序列化时直接用指针偏移读取字节,不需要额外拷贝子vector。

优化后的示例代码

#include <vector>
#include <cstring>
#include <algorithm>
#include <cstdint>
#include <type_traits>

// 假设Data类定义如下
struct Data {
    int32_t Int32;
    int64_t Int64;
    float Float;
    double Double;
};

// 将int32转为大端字节序的vector
std::vector<uint8_t> encode(int32_t value) {
    std::vector<uint8_t> bytes(4);
    const uint32_t be_val = htonl(static_cast<uint32_t>(value));
    std::memcpy(bytes.data(), &be_val, sizeof(be_val));
    return bytes;
}

// 将int64转为大端字节序的vector
std::vector<uint8_t> encode(int64_t value) {
    std::vector<uint8_t> bytes(8);
    const uint64_t be_val = htonll(static_cast<uint64_t>(value));
    std::memcpy(bytes.data(), &be_val, sizeof(be_val));
    return bytes;
}

// 通用序列化单个值到目标vector
template<typename T>
void serialize_val(const T& val, std::vector<uint8_t>& out) {
    if constexpr (std::is_same_v<T, float>) {
        uint32_t tmp;
        std::memcpy(&tmp, &val, sizeof(float));
        tmp = htonl(tmp);
        const uint8_t* bytes = reinterpret_cast<const uint8_t*>(&tmp);
        out.insert(out.end(), bytes, bytes + sizeof(float));
    } else if constexpr (std::is_same_v<T, double>) {
        uint64_t tmp;
        std::memcpy(&tmp, &val, sizeof(double));
        tmp = htonll(tmp);
        const uint8_t* bytes = reinterpret_cast<const uint8_t*>(&tmp);
        out.insert(out.end(), bytes, bytes + sizeof(double));
    } else {
        auto bytes = encode(val);
        out.insert(out.end(), bytes.begin(), bytes.end());
    }
}

std::vector<uint8_t> serialize(Data& D) {
    std::vector<uint8_t> serialized_data;
    
    serialize_val(D.Int32, serialized_data);
    serialize_val(D.Int64, serialized_data);
    serialize_val(D.Float, serialized_data);
    serialize_val(D.Double, serialized_data);
    
    return serialized_data;
}

// 从字节指针解析int32(大端转主机序)
int32_t decode_int32(const uint8_t* bytes) {
    uint32_t be_val;
    std::memcpy(&be_val, bytes, sizeof(be_val));
    return static_cast<int32_t>(ntohl(be_val));
}

// 从字节指针解析int64(大端转主机序)
int64_t decode_int64(const uint8_t* bytes) {
    uint64_t be_val;
    std::memcpy(&be_val, bytes, sizeof(be_val));
    return static_cast<int64_t>(ntohll(be_val));
}

// 通用从字节指针反序列化单个值
template<typename T>
T deserialize_val(const uint8_t*& ptr) {
    T result;
    if constexpr (std::is_same_v<T, float>) {
        uint32_t tmp;
        std::memcpy(&tmp, ptr, sizeof(float));
        tmp = ntohl(tmp);
        std::memcpy(&result, &tmp, sizeof(float));
        ptr += sizeof(float);
    } else if constexpr (std::is_same_v<T, double>) {
        uint64_t tmp;
        std::memcpy(&tmp, ptr, sizeof(double));
        tmp = ntohll(tmp);
        std::memcpy(&result, &tmp, sizeof(double));
        ptr += sizeof(double);
    } else if constexpr (std::is_same_v<T, int32_t>) {
        result = decode_int32(ptr);
        ptr += sizeof(int32_t);
    } else if constexpr (std::is_same_v<T, int64_t>) {
        result = decode_int64(ptr);
        ptr += sizeof(int64_t);
    }
    return result;
}

Data deserialize(std::vector<uint8_t>& Bytes) {
    Data D2;
    const uint8_t* ptr = Bytes.data();
    
    D2.Int32 = deserialize_val<int32_t>(ptr);
    D2.Int64 = deserialize_val<int64_t>(ptr);
    D2.Float = deserialize_val<float>(ptr);
    D2.Double = deserialize_val<double>(ptr);
    
    return D2;
}

内容的提问来源于stack exchange,提问作者Sao Petrik

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 17:27:15