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;
}
}
- 一种简单的方法是将对象的成员变量以特定的格式(如 CSV - 逗号分隔值)写入文件。例如,假设有一个Person类,包含姓名和年龄两个成员变量。
- 反序列化
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;
}
}
- 使用fstream库的二进制模式来写入对象的内存表示。不过需要注意字节序等问题。
- 反序列化
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;
}
- 以下是使用 Boost.Serialization 对Person类进行序列化和反序列化的简单示例。
二、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_ptr或std::shared_ptr来管理动态分配的内存。
- // 不需要手动释放内存,当p离开作用域时,Person对象会被自动销毁
- std::shared_ptr是共享所有权的智能指针,用于多个对象共享同一个资源的情况。例如,多个对象可能需要共享对同一个数据库连接对象的引用。
手动内存管理(使用new和delete) - 当使用new在堆上分配内存时,必须在适当的时候使用delete来释放内存。错误地使用delete(如多次删除同一个对象或者使用已经删除的对象)会导致程序出错,如段错误等。并且如果在delete之后还尝试访问对象成员,也是未定义行为。
相关文章:
C++ 中的序列化和反序列化
一、C 中的序列化和反序列化 (一)基本概念 在 C 中,序列化是将对象转换为字节流的过程,反序列化则是从字节流重新构建对象的过程。这对于存储对象状态到文件、网络传输等场景非常有用。 (二)简单的序列化…...

我的Github学生认证申请过程
先说结论:很简单。 学生认证链接:GitHub Education GitHub 1. 首先你得绑定edu邮箱。这个应该没什么问题,Github也会提示。 2. 我是在学校里面、使用流量而非WiFi申请的,听说地理位置很重要,该给的权限(…...
信奥题解:勾股数计算中的浮点数精度问题
来源: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?1.2 Composition API 的核心工具1.3 基础用法示例 二、响应式系统2…...

【AI知识】逻辑回归介绍+ 做二分类任务的实例(代码可视化)
1. 分类的基本概念 在机器学习的有监督学习中,分类一种常见任务,它的目标是将输入数据分类到预定的类别中。具体来说: 分类任务的常见应用: 垃圾邮件分类:判断一封电子邮件是否是垃圾邮件 。 医学诊断:…...
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是轻量型数据库,并且免费,没有服务恢复数据。 Oracle是重量型数据库,收费,Oracle公司对Oracle数据库有任何服务。 1.对事务的提交 MySQL默认是自动提交,而Oracle默认不自动提交࿰…...

实验12 C语言连接和操作MySQL数据库
一、安装MySQL 1、使用包管理器安装MySQL sudo apt update sudo apt install mysql-server2、启动MySQL服务: sudo systemctl start mysql3、检查MySQL服务状态: sudo systemctl status mysql二、安装MySQL开发库 sudo apt-get install libmysqlcli…...

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

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

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

基于米尔全志T527开发板的OpenCV进行手势识别方案
本文将介绍基于米尔电子MYD-LT527开发板(米尔基于全志T527开发板)的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,我们需要判断这个A方法是否存在事务,并且使用异步执行动作B; 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制作伤害浮动数字
效果演示: 首先创建一个控件UI 添加画布和文本 文本设置样式 添加伤害浮动动画,根据自己喜好调整,我设置了缩放和不透明度 添加绑定 转到事件图表,事件构造设置动画 创建actor蓝图类 添加widget 获取位置 设置位移 创建一个被击中…...

学习日志024--opencv中处理轮廓的函数
目录 前言 一、 梯度处理的sobel算子函数 功能 参数 返回值 代码演示 二、梯度处理拉普拉斯算子 功能 参数 返回值 代码演示 三、Canny算子 功能 参数 返回值 代码演示 四、findContours函数与drawContours函数 功能 参数 返回值 代码演示 …...

(2024年最新)Linux(Ubuntu) 中配置静态IP(包含解决每次重启后配置文件失效问题)
Hello! 亲爱的小伙伴们,大家好呀(Smile~)!我是Huazzi,欢迎观看本篇博客,接下来让我们一起来学习一下Ubuntu 中如何配置静态IP吧!祝你有所收获! 提前对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…...

前端导出带有合并单元格的列表
// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...
Golang dig框架与GraphQL的完美结合
将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用,可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器,能够帮助开发者更好地管理复杂的依赖关系,而 GraphQL 则是一种用于 API 的查询语言,能够提…...
OpenLayers 分屏对比(地图联动)
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能,和卷帘图层不一样的是,分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...

全志A40i android7.1 调试信息打印串口由uart0改为uart3
一,概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本:2014.07; Kernel版本:Linux-3.10; 二,Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01),并让boo…...

C# 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...

浪潮交换机配置track检测实现高速公路收费网络主备切换NQA
浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求,本次涉及的主要是收费汇聚交换机的配置,浪潮网络设备在高速项目很少,通…...

基于Java+VUE+MariaDB实现(Web)仿小米商城
仿小米商城 环境安装 nodejs maven JDK11 运行 mvn clean install -DskipTestscd adminmvn spring-boot:runcd ../webmvn spring-boot:runcd ../xiaomi-store-admin-vuenpm installnpm run servecd ../xiaomi-store-vuenpm installnpm run serve 注意:运行前…...

CVPR2025重磅突破:AnomalyAny框架实现单样本生成逼真异常数据,破解视觉检测瓶颈!
本文介绍了一种名为AnomalyAny的创新框架,该方法利用Stable Diffusion的强大生成能力,仅需单个正常样本和文本描述,即可生成逼真且多样化的异常样本,有效解决了视觉异常检测中异常样本稀缺的难题,为工业质检、医疗影像…...
Vue 模板语句的数据来源
🧩 Vue 模板语句的数据来源:全方位解析 Vue 模板(<template> 部分)中的表达式、指令绑定(如 v-bind, v-on)和插值({{ }})都在一个特定的作用域内求值。这个作用域由当前 组件…...

论文阅读:Matting by Generation
今天介绍一篇关于 matting 抠图的文章,抠图也算是计算机视觉里面非常经典的一个任务了。从早期的经典算法到如今的深度学习算法,已经有很多的工作和这个任务相关。这两年 diffusion 模型很火,大家又开始用 diffusion 模型做各种 CV 任务了&am…...