当前位置: 首页 > news >正文

C++ 中的序列化和反序列化

一、C++ 中的序列化和反序列化

(一)基本概念

在 C++ 中,序列化是将对象转换为字节流的过程,反序列化则是从字节流重新构建对象的过程。这对于存储对象状态到文件、网络传输等场景非常有用。

(二)简单的序列化和反序列化实现方式

1. 基于文本格式

  • 序列化
    • 一种简单的方法是将对象的成员变量以特定的格式(如 CSV - 逗号分隔值)写入文件。例如,假设有一个Person类,包含姓名和年龄两个成员变量。
      #include <iostream>
      #include <fstream>
      #include <string>


      class Person {
      public:
          std::string name;
          int age;
          Person(const std::string& n, int a) : name(n), age(a) {}
      };


      void serializeToText(const Person& p, const std::string& filename) {
          std::ofstream file(filename);
          if (file.is_open()) {
              file << p.name << "," << p.age << std::endl;
              file.close();
          } else {
              std::cerr << "无法打开文件进行序列化。" << std::endl;
          }
      }
  • 反序列化
    Person deserializeFromText(const std::string& filename) {
        std::ifstream file(filename);
        Person p("", 0);
        if (file.is_open()) {
            std::string line;
            if (std::getline(file, line)) {
                size_t pos = line.find(',');
                if (pos!= std::string::npos) {
                    p.name = line.substr(0, pos);
                    p.age = std::stoi(line.substr(pos + 1));
                }
            }
            file.close();
        } else {
            std::cerr << "无法打开文件进行反序列化。" << std::endl;
        }
        return p;
    }

2. 使用二进制格式(更高效,但不可读)

  • 序列化
    • 使用fstream库的二进制模式来写入对象的内存表示。不过需要注意字节序等问题。
      void serializeToBinary(const Person& p, const std::string& filename) {
          std::ofstream file(filename, std::ios::binary);
          if (file.is_open()) {
              // 先写入姓名长度
              int nameLength = p.name.length();
              file.write(reinterpret_cast<const char*>(&nameLength), sizeof(int));
              // 再写入姓名内容
              file.write(p.name.c_str(), nameLength);
              // 写入年龄
              file.write(reinterpret_cast<const char*>(&p.age), sizeof(int));
              file.close();
          } else {
              std::cerr << "无法打开文件进行二进制序列化。" << std::endl;
          }
      }
  • 反序列化
    Person deserializeFromBinary(const std::string& filename) {
        std::ifstream file(filename, std::ios::binary);
        Person p("", 0);
        if (file.is_open()) {
            // 先读取姓名长度
            int nameLength;
            file.read(reinterpret_cast<char*>(&nameLength), sizeof(int));
            char* buffer = new char[nameLength + 1];
            // 读取姓名内容
            file.read(buffer, nameLength);
            buffer[nameLength] = '\0';
            p.name = buffer;
            delete[] buffer;
            // 读取年龄
            file.read(reinterpret_cast<char*>(&p.age), sizeof(int));
            file.close();
        } else {
            std::cerr << "无法打开文件进行二进制反序列化。" << std::endl;
        }
        return p;
    }

(三)使用第三方库(如 Boost.Serialization)进行序列化和反序列化

  • 安装和配置 Boost 库
    • 首先需要下载并安装 Boost 库,这通常涉及从 Boost 官方网站获取源代码,然后通过编译安装到系统中。安装过程因操作系统而异。
  • 使用示例
    • 以下是使用 Boost.Serialization 对Person类进行序列化和反序列化的简单示例。

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


      class Person {
      public:
          std::string name;
          int age;
          Person(const std::string& n, int a) : name(n), age(a) {}
          // 为了让Boost.Serialization能够访问私有成员,需要添加这两个友元函数
          friend class boost::serialization::access;
          template<class Archive>
          void serialize(Archive& ar, const unsigned int version) {
              ar & name;
              ar & age;
          }
      };


      void serializeWithBoost(const Person& p, const std::string& filename) {
          std::ofstream file(filename);
          if (file.is_open()) {
              boost::archive::text_oarchive oa(file);
              oa << p;
              file.close();
          } else {
              std::cerr << "无法打开文件进行Boost序列化。" << std::endl;
          }
      }


      Person deserializeWithBoost(const std::string& filename) {
          std::ifstream file(filename);
          Person p("", 0);
          if (file.is_open()) {
              boost::archive::text_iarchive ia(file);
              ia >> p;
              file.close();
          } else {
              std::cerr << "无法打开文件进行Boost反序列化。" << std::endl;
          }
          return p;
      }

二、C++ 中的对象生命周期管理

(一)对象生命周期阶段

  • 创建
    • 栈对象:在函数内部定义的对象,当程序执行到对象定义处时,会调用对象的构造函数进行创建。例如Person p("Alice", 30);,这里p是一个栈对象,它的生命周期从定义处开始,到所在的代码块结束(如函数返回)。
    • 堆对象:通过new关键字在堆上分配内存创建对象。例如Person* p = new Person("Bob", 25);,此时需要手动管理内存,使用delete来释放内存。
  • 使用:在对象的生命周期内,可以通过对象的成员函数访问和修改对象的状态,就像p->getName()p.setName("Charlie");这样的操作。
  • 销毁
    • 栈对象:当栈对象所在的代码块结束时,对象的析构函数会被自动调用,用于清理对象占用的资源。
    • 堆对象:需要手动调用delete来释放堆上对象占用的内存,并且在调用delete后,对象的析构函数会被调用。如果忘记调用delete,就会导致内存泄漏。

(二)内存管理和资源清理

  • RAII(Resource Acquisition Is Initialization)
    • 这是 C++ 中一种重要的资源管理机制。核心思想是将资源的获取和初始化放在构造函数中,将资源的释放放在析构函数中。例如,使用std::unique_ptrstd::shared_ptr来管理动态分配的内存。
    • // 不需要手动释放内存,当p离开作用域时,Person对象会被自动销毁
    • std::shared_ptr是共享所有权的智能指针,用于多个对象共享同一个资源的情况。例如,多个对象可能需要共享对同一个数据库连接对象的引用。
      手动内存管理(使用
      newdelete
    • 当使用new在堆上分配内存时,必须在适当的时候使用delete来释放内存。错误地使用delete(如多次删除同一个对象或者使用已经删除的对象)会导致程序出错,如段错误等。并且如果在delete之后还尝试访问对象成员,也是未定义行为。

相关文章:

C++ 中的序列化和反序列化

一、C 中的序列化和反序列化 &#xff08;一&#xff09;基本概念 在 C 中&#xff0c;序列化是将对象转换为字节流的过程&#xff0c;反序列化则是从字节流重新构建对象的过程。这对于存储对象状态到文件、网络传输等场景非常有用。 &#xff08;二&#xff09;简单的序列化…...

我的Github学生认证申请过程

先说结论&#xff1a;很简单。 学生认证链接&#xff1a;GitHub Education GitHub 1. 首先你得绑定edu邮箱。这个应该没什么问题&#xff0c;Github也会提示。 2. 我是在学校里面、使用流量而非WiFi申请的&#xff0c;听说地理位置很重要&#xff0c;该给的权限&#xff08…...

信奥题解:勾股数计算中的浮点数精度问题

来源:GESP C++ 二级模拟题 本文给出官方参考答案的详细解析,包括每一部分的功能和关键点,以及与浮点数精度相关的问题的分析。 题目描述 勾股数是很有趣的数学概念。如果三个正整数a 、b 、c ,满足 a 2 + b 2 = c 2 a^2 + b^2 = c^2 a2+b2=c2 ,而且1 ≤ a ≤ b ≤ c ,…...

重生之我在学Vue--第2天 Vue 3 Composition API 与响应式系统

重生之我在学Vue–第2天 Vue 3 Composition API 与响应式系统 文章目录 重生之我在学Vue--第2天 Vue 3 Composition API 与响应式系统前言一、Composition API 核心概念1.1 什么是 Composition API&#xff1f;1.2 Composition API 的核心工具1.3 基础用法示例 二、响应式系统2…...

【AI知识】逻辑回归介绍+ 做二分类任务的实例(代码可视化)

1. 分类的基本概念 在机器学习的有监督学习中&#xff0c;分类一种常见任务&#xff0c;它的目标是将输入数据分类到预定的类别中。具体来说&#xff1a; 分类任务的常见应用&#xff1a; 垃圾邮件分类&#xff1a;判断一封电子邮件是否是垃圾邮件 。 医学诊断&#xff1a;…...

Mysql 笔记2 emp dept HRs

-- 注意事项 -- 1.给数据库和表起名字时尽量选择全小写 -- 2.作为筛选条件的字符串是否区分大小写看设置的校对规则utf8_bin 区分 drop database if exists hrs; create database hrs default charset utf8 collate utf8_general_ci;use hrs; drop table if exists tb_emp; dro…...

MySQL和Oracle的区别

MySQL和Oracle的区别 MySQL是轻量型数据库&#xff0c;并且免费&#xff0c;没有服务恢复数据。 Oracle是重量型数据库&#xff0c;收费&#xff0c;Oracle公司对Oracle数据库有任何服务。 1.对事务的提交 MySQL默认是自动提交&#xff0c;而Oracle默认不自动提交&#xff0…...

实验12 C语言连接和操作MySQL数据库

一、安装MySQL 1、使用包管理器安装MySQL sudo apt update sudo apt install mysql-server2、启动MySQL服务&#xff1a; sudo systemctl start mysql3、检查MySQL服务状态&#xff1a; sudo systemctl status mysql二、安装MySQL开发库 sudo apt-get install libmysqlcli…...

09篇--图片的水印添加(掩膜的运用)

如何添加水印&#xff1f; 添加水印其实可以理解为将一张图片中的某个物体或者图案提取出来&#xff0c;然后叠加到另一张图片上。具体的操作思想是通过将原始图片转换成灰度图&#xff0c;并进行二值化处理&#xff0c;去除背景部分&#xff0c;得到一个类似掩膜的图像。然后…...

sql-labs(21-25)

第21关 第一步 可以发现cookie是经过64位加密的 我们试试在这里注入 选择给他编码 发现可以成功注入 爆出表名 爆出字段 爆出数据 第22关 跟二十一关一模一样 闭合换成" 第 23 关 第二十三关重新回到get请求&#xff0c;会发现输入单引号报错&#xff0c;但是注释符…...

CTF知识集-命令执行

CTF知识集-命令执行 写在开头可能会用到的提醒 ;可以用%0a来替换 是shell_exec的缩写 ls | tee 1 把ls的输出内容存入1这个文件 shell查看文件的几种方式&#xff0c;tac | more | less | tail | sort | tac | cat | head | od | expand 针对flag 可以用grep { flag.php来…...

基于米尔全志T527开发板的OpenCV进行手势识别方案

本文将介绍基于米尔电子MYD-LT527开发板&#xff08;米尔基于全志T527开发板&#xff09;的OpenCV手势识别方案测试。 摘自优秀创作者-小火苗 米尔基于全志T527开发板 一、软件环境安装 1.安装OpenCV sudo apt-get install libopencv-dev python3-opencv 2.安装pip sudo apt…...

Htpp中web通讯发送post(上传文件)、get请求

一、正常发送post请求 1、引入pom文件 <dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5</version></dependency>2、这个是发送至正常的post、get请求 import org…...

【论文阅读笔记】HunyuanVideo: A Systematic Framework For Large Video Generative Models

HunyuanVideo: A Systematic Framework For Large Video Generative Models 前言引言Overview数据预处理数据过滤数据注释 模型架构设计3D Variational Auto-encoder Designtraininginference 统一的图像和视频生成架构Text encoderModel ScalingImage model scaling lawvideo …...

SpringBoot的事务钩子函数

如果需要在A方法执行完成之后做一个不影响主方法运行的动作B&#xff0c;我们需要判断这个A方法是否存在事务&#xff0c;并且使用异步执行动作B&#xff1b; import org.springframework.transaction.support.TransactionSynchronization; import org.springframework.transa…...

源码安装PHP-7.2.19

源码安装PHP-7.2.19 1.解压 tar -xjvf php-7.2.19.tar.bz2.编译 -prefix安装路径 cd php-7.2.19 ./configure --prefix/home/work/study 成功输出 3.make(构建) makemake testmake installlinux对php操作的一些命令 # 进入到php [rootvdb1 study]# cd php/ [rootvdb1 st…...

UE5制作伤害浮动数字

效果演示&#xff1a; 首先创建一个控件UI 添加画布和文本 文本设置样式 添加伤害浮动动画&#xff0c;根据自己喜好调整&#xff0c;我设置了缩放和不透明度 添加绑定 转到事件图表&#xff0c;事件构造设置动画 创建actor蓝图类 添加widget 获取位置 设置位移 创建一个被击中…...

学习日志024--opencv中处理轮廓的函数

目录 前言​​​​​​​ 一、 梯度处理的sobel算子函数 功能 参数 返回值 代码演示 二、梯度处理拉普拉斯算子 功能 参数 返回值 代码演示 三、Canny算子 功能 参数 返回值 代码演示 四、findContours函数与drawContours函数 功能 参数 返回值 代码演示 …...

(2024年最新)Linux(Ubuntu) 中配置静态IP(包含解决每次重启后配置文件失效问题)

Hello! 亲爱的小伙伴们&#xff0c;大家好呀&#xff08;Smile~&#xff09;&#xff01;我是Huazzi&#xff0c;欢迎观看本篇博客&#xff0c;接下来让我们一起来学习一下Ubuntu 中如何配置静态IP吧&#xff01;祝你有所收获&#xff01; 提前对Linux有所了解的小伙伴应该知道…...

DPDK用户态协议栈-TCP Posix API 2

tcp posix api send发送 ssize_t nsend(int sockfd, const void *buf, size_t len, __attribute__((unused))int flags) {ssize_t length 0;void* hostinfo get_host_fromfd(sockfd);if (hostinfo NULL) {return -1;}struct ln_tcp_stream* stream (struct ln_tcp_stream…...

[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?

&#x1f9e0; 智能合约中的数据是如何在区块链中保持一致的&#xff1f; 为什么所有区块链节点都能得出相同结果&#xff1f;合约调用这么复杂&#xff0c;状态真能保持一致吗&#xff1f;本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里&#xf…...

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…...

MPNet:旋转机械轻量化故障诊断模型详解python代码复现

目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...

【杂谈】-递归进化:人工智能的自我改进与监管挑战

递归进化&#xff1a;人工智能的自我改进与监管挑战 文章目录 递归进化&#xff1a;人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管&#xff1f;3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...

docker详细操作--未完待续

docker介绍 docker官网: Docker&#xff1a;加速容器应用程序开发 harbor官网&#xff1a;Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台&#xff0c;用于将应用程序及其依赖项&#xff08;如库、运行时环…...

2024年赣州旅游投资集团社会招聘笔试真

2024年赣州旅游投资集团社会招聘笔试真 题 ( 满 分 1 0 0 分 时 间 1 2 0 分 钟 ) 一、单选题(每题只有一个正确答案,答错、不答或多答均不得分) 1.纪要的特点不包括()。 A.概括重点 B.指导传达 C. 客观纪实 D.有言必录 【答案】: D 2.1864年,()预言了电磁波的存在,并指出…...

Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具

文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...

QT: `long long` 类型转换为 `QString` 2025.6.5

在 Qt 中&#xff0c;将 long long 类型转换为 QString 可以通过以下两种常用方法实现&#xff1a; 方法 1&#xff1a;使用 QString::number() 直接调用 QString 的静态方法 number()&#xff0c;将数值转换为字符串&#xff1a; long long value 1234567890123456789LL; …...

[Java恶补day16] 238.除自身以外数组的乘积

给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O(n) 时间复杂度…...

精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南

精益数据分析&#xff08;97/126&#xff09;&#xff1a;邮件营销与用户参与度的关键指标优化指南 在数字化营销时代&#xff0c;邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天&#xff0c;我们将深入解析邮件打开率、网站可用性、页面参与时…...