当前位置: 首页 > 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…...

SciencePlots——绘制论文中的图片

文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了&#xff1a;一行…...

Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例

使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件&#xff0c;常用于在两个集合之间进行数据转移&#xff0c;如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model&#xff1a;绑定右侧列表的值&…...

SCAU期末笔记 - 数据分析与数据挖掘题库解析

这门怎么题库答案不全啊日 来简单学一下子来 一、选择题&#xff08;可多选&#xff09; 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘&#xff1a;专注于发现数据中…...

前端导出带有合并单元格的列表

// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...

【解密LSTM、GRU如何解决传统RNN梯度消失问题】

解密LSTM与GRU&#xff1a;如何让RNN变得更聪明&#xff1f; 在深度学习的世界里&#xff0c;循环神经网络&#xff08;RNN&#xff09;以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而&#xff0c;传统RNN存在的一个严重问题——梯度消失&#…...

华为OD机试-食堂供餐-二分法

import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...

tree 树组件大数据卡顿问题优化

问题背景 项目中有用到树组件用来做文件目录&#xff0c;但是由于这个树组件的节点越来越多&#xff0c;导致页面在滚动这个树组件的时候浏览器就很容易卡死。这种问题基本上都是因为dom节点太多&#xff0c;导致的浏览器卡顿&#xff0c;这里很明显就需要用到虚拟列表的技术&…...

Java + Spring Boot + Mybatis 实现批量插入

在 Java 中使用 Spring Boot 和 MyBatis 实现批量插入可以通过以下步骤完成。这里提供两种常用方法&#xff1a;使用 MyBatis 的 <foreach> 标签和批处理模式&#xff08;ExecutorType.BATCH&#xff09;。 方法一&#xff1a;使用 XML 的 <foreach> 标签&#xff…...

Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档&#xff09;&#xff0c;如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下&#xff0c;风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...

【分享】推荐一些办公小工具

1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由&#xff1a;大部分的转换软件需要收费&#xff0c;要么功能不齐全&#xff0c;而开会员又用不了几次浪费钱&#xff0c;借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...