如何实现序列化和反序列化?如何处理对象的生命周期管理?

序列化和反序列化

实现思路

  • 序列化 :将对象的状态信息转换为可以存储或传输的格式,通常是字节流。
    1. 确定要序列化的对象的数据成员。
    2. 将这些数据成员按照一定的规则(如二进制、文本、JSON、XML 等)编码为字节序列。
    3. 将生成的字节序列存储到文件或发送到网络。
  • 反序列化 :将字节流恢复为对象的状态信息。
    1. 从文件或网络接收字节序列。
    2. 按照序列化时使用的规则解码字节序列。
    3. 根据解码后的数据成员创建或更新对象。
cpp 复制代码
#include <iostream>
#include <fstream>
#include <string>

class SerializableObject {
private:
    int data1;
    double data2;
    std::string data3;

public:
    SerializableObject(int d1 = 0, double d2 = 0.0, const std::string& d3 = "") : data1(d1), data2(d2), data3(d3) {}

    // 序列化函数
    void serialize(const std::string& filename) const {
        std::ofstream file(filename, std::ios::binary);
        if (file.is_open()) {
            // 写入数据成员
            file.write(reinterpret_cast<const char*>(&data1), sizeof(data1));
            file.write(reinterpret_cast<const char*>(&data2), sizeof(data2));
            // 先写入字符串长度
            size_t len = data3.length();
            file.write(reinterpret_cast<const char*>(&len), sizeof(len));
            // 再写入字符串内容
            file.write(data3.c_str(), len);
            file.close();
        } else {
            std::cerr << "Failed to open file for serialization." << std::endl;
        }
    }

    // 反序列化函数
    void deserialize(const std::string& filename) {
        std::ifstream file(filename, std::ios::binary);
        if (file.is_open()) {
            // 读取数据成员
            file.read(reinterpret_cast<char*>(&data1), sizeof(data1));
            file.read(reinterpret_cast<char*>(&data2), sizeof(data2));
            // 先读取字符串长度
            size_t len;
            file.read(reinterpret_cast<char*>(&len), sizeof(len));
            // 再读取字符串内容
            data3.resize(len);
            file.read(&data3[0], len);
            file.close();
        } else {
            std::cerr << "Failed to open file for deserialization." << std::endl;
        }
    }

    void display() const {
        std::cout << "data1: " << data1 << ", data2: " << data2 << ", data3: " << data3 << std::endl;
    }
};


int main() {
    SerializableObject obj(42, 3.14, "Hello, World!");
    std::string filename = "object.bin";

    // 序列化
    obj.serialize(filename);
    std::cout << "Serialized object: " << std::endl;
    obj.display();

    SerializableObject newObj;
    // 反序列化
    newObj.deserialize(filename);
    std::cout << "Deserialized object: " << std::endl;
    newObj.display();

    return 0;
}

代码解释

  • SerializableObject 类包含三个数据成员:data1(整数)、data2(双精度浮点数)和 data3(字符串)。
  • serialize 函数:
    • 使用 std::ofstream 以二进制模式打开文件。
    • 对于 data1data2,使用 file.write 将它们的二进制表示写入文件。
    • 对于 data3,先写入字符串的长度,再写入字符串的内容。
  • deserialize 函数:
    • 使用 std::ifstream 以二进制模式打开文件。
    • 对于 data1data2,使用 file.read 读取它们的二进制表示。
    • 对于 data3,先读取字符串的长度,再读取字符串的内容。
  • display 函数:打印对象的数据成员。

如何处理对象的生命周期管理?

实现思路

  • 构造函数:用于对象的初始化,可进行资源分配和成员初始化。
  • 析构函数:用于对象销毁时释放资源,如释放动态分配的内存、关闭文件等。
  • 拷贝构造函数和拷贝赋值运算符:控制对象的拷贝行为,避免浅拷贝导致的资源问题。
  • 移动构造函数和移动赋值运算符:实现对象资源的高效移动,避免不必要的拷贝。
cpp 复制代码
#include <iostream>
#include <string>
#include <utility>

class ResourceManagingObject {
private:
    int* data;
    size_t size;

public:
    // 构造函数
    ResourceManagingObject(size_t s = 0) : size(s) {
        if (s > 0) {
            data = new int[s];
            for (size_t i = 0; i < s; ++i) {
                data[i] = i;
            }
        } else {
            data = nullptr;
        }
    }

    // 析构函数
    ~ResourceManagingObject() {
        delete[] data;
    }

    // 拷贝构造函数
    ResourceManagingObject(const ResourceManagingObject& other) : size(other.size) {
        if (other.data) {
            data = new int[size];
            for (size_t i = 0; i < size; ++i) {
                data[i] = other.data[i];
            }
        } else {
            data = nullptr;
        }
    }

    // 拷贝赋值运算符
    ResourceManagingObject& operator=(const ResourceManagingObject& other) {
        if (this == &other) return *this;
        delete[] data;
        size = other.size;
        if (other.data) {
            data = new int[size];
            for (size_t i = 0; i < size; ++i) {
                data[i] = other.data[i];
            }
        } else {
            data = nullptr;
        }
        return *this;
    }

    // 移动构造函数
    ResourceManagingObject(ResourceManagingObject&& other) noexcept : data(other.data), size(other.size) {
        other.data = nullptr;
        other.size = 0;
    }

    // 移动赋值运算符
    ResourceManagingObject& operator=(ResourceManagingObject&& other) noexcept {
        if (this == &other) return *this;
        delete[] data;
        data = other.data;
        size = other.size;
        other.data = nullptr;
        other.size = 0;
        return *this;
    }

    void display() const {
        if (data) {
            for (size_t i = 0; i < size; ++i) {
                std::cout << data[i] << " ";
            }
            std::cout << std::endl;
        } else {
            std::cout << "No data." << std::endl;
        }
    }
};


int main() {
    ResourceManagingObject obj1(5);
    std::cout << "Original object: ";
    obj1.display();

    // 拷贝构造
    ResourceManagingObject obj2 = obj1;
    std::cout << "Copied object: ";
    obj2.display();

    // 移动构造
    ResourceManagingObject obj3 = std::move(obj1);
    std::cout << "Moved object: ";
    obj3.display();
    std::cout << "Original object after move: ";
    obj1.display();

    return 0;
}

代码解释

  • ResourceManagingObject 类管理一个动态分配的整数数组。
  • 构造函数:根据大小分配内存并初始化数组元素。
  • 析构函数:释放动态分配的内存。
  • 拷贝构造函数和拷贝赋值运算符:深拷贝资源,避免浅拷贝导致的资源共享和潜在的内存问题。
  • 移动构造函数和移动赋值运算符:将资源从源对象移动到目标对象,源对象放弃资源所有权。
相关推荐
FANGhelloworld29 分钟前
C++小工具封装 —— NetWork(TCP、UDP)
c++·网络协议·tcp/ip·udp
蚰蜒螟1 小时前
C++ 中,标准库容器emplace 和 移动构造函数区别
开发语言·c++
Hera_Yc.H2 小时前
C++之二:类和对象
开发语言·c++
毒丐2 小时前
VirtualBox使用教程
java·服务器·c++
葟雪儿3 小时前
海思芯片 交叉编译curl
linux·运维·服务器·开发语言·c++·嵌入式硬件
Octopus20774 小时前
【C++】红黑树(万字)
c++·笔记·学习
落笔映浮华丶4 小时前
C++(进阶) 第4章 map和set的使⽤
c++
毒丐5 小时前
FreeBSD安装教程
c语言·c++
无为扫地僧5 小时前
五、windows上vscode构建c/c++环境
c++·vscode·c