C++中的拷贝构造函数和深拷贝、浅拷贝,如何在C++中实现类和对象的序列化与反序列化?

C++中的拷贝构造函数和深拷贝、浅拷贝
拷贝构造函数:
拷贝构造函数是一种特殊的构造函数,它接受一个对其同类的常量引用作为参数,并用于初始化新创建的对象。其主要作用是实现一个类的对象到另一个相同类型对象的拷贝。

拷贝构造函数的原型通常如下:

ClassName(const ClassName &obj);

其中 ClassName 是类的名称,&obj 是对同类型对象的引用。

深拷贝与浅拷贝:
深拷贝和浅拷贝主要涉及到对象内部的资源(如动态分配的内存)的拷贝方式。

浅拷贝(Shallow Copy):
浅拷贝只复制对象的指针,而不复制指针所指向的实际数据。因此,原对象和拷贝后的对象将共享同一块内存区域。这意味着,如果其中一个对象修改了这块内存区域,那么这种变化也会反映到另一个对象上。浅拷贝可能导致数据的不一致性和潜在的资源释放问题(如双重释放)。

深拷贝(Deep Copy):
深拷贝会复制对象指针所指向的所有数据,并为新对象分配新的内存区域。这样,原对象和拷贝后的对象将不共享任何数据。因此,修改其中一个对象不会影响另一个对象。深拷贝确保了对象的独立性,但可能会消耗更多的内存。

例子:
考虑一个简单的类,它包含一个动态分配的数组:

class Example {  
public:  int* arr;  int size;  // 构造函数  Example(int size) : size(size) {  arr = new int[size];  }  // 拷贝构造函数(浅拷贝)  Example(const Example &other) : size(other.size) {  arr = other.arr; // 只复制了指针,没有复制数组数据  }  // 析构函数  ~Example() {  delete[] arr;  }  
};

在这个例子中,拷贝构造函数执行的是浅拷贝,因为它只复制了 arr 指针,而没有复制指针指向的内存区域。如果两个 Example 对象共享同一块内存,那么释放其中一个对象的内存将会导致另一个对象的数据变得无效。

为了实现深拷贝,拷贝构造函数需要复制数组数据:

// 深拷贝的拷贝构造函数  
Example(const Example &other) : size(other.size) {  arr = new int[size];  for (int i = 0; i < size; ++i) {  arr[i] = other.arr[i]; // 复制数组数据  }  
}

在这个深拷贝的实现中,新对象的 arr 指针指向一块新的内存区域,这块内存区域是原对象数组数据的副本。这样,新对象和原对象就不会共享数据了。

如何在C++中实现类和对象的序列化与反序列化?
在C++中实现类和对象的序列化和反序列化通常涉及将对象的状态转换为可以存储或传输的格式(如二进制或文本),以及从这种格式中恢复对象的状态。这通常通过重载输出运算符(<<)和输入运算符(>>)或使用第三方库(如Boost.Serialization或Protocol Buffers)来完成。

下面是一个简单的例子,展示了如何在C++中手动实现序列化和反序列化。假设我们有一个简单的Person类:

#include <iostream>  
#include <fstream>  
#include <string>  class Person {  
public:  std::string name;  int age;  // 序列化函数  void serialize(std::ostream& os) const {  os.write(reinterpret_cast<const char*>(&age), sizeof(age));  std::string lengthStr = std::to_string(name.length());  os.write(lengthStr.c_str(), lengthStr.length());  os << name;  }  // 反序列化函数  void deserialize(std::istream& is) {  is.read(reinterpret_cast<char*>(&age), sizeof(age));  std::string lengthStr;  is >> lengthStr;  name.resize(std::stoi(lengthStr));  is >> name;  }  
};  // 重载输出运算符以进行序列化  
std::ostream& operator<<(std::ostream& os, const Person& person) {  person.serialize(os);  return os;  
}  // 重载输入运算符以进行反序列化  
std::istream& operator>>(std::istream& is, Person& person) {  person.deserialize(is);  return is;  
}  int main() {  // 创建并序列化一个对象  Person person;  person.name = "Alice";  person.age = 30;  std::ofstream ofs("person.dat", std::ios::binary);  ofs << person;  ofs.close();  // 反序列化一个对象  Person deserializedPerson;  std::ifstream ifs("person.dat", std::ios::binary);  ifs >> deserializedPerson;  ifs.close();  // 输出反序列化后的对象  std::cout << "Deserialized Person: " << deserializedPerson.name << ", Age: " << deserializedPerson.age << std::endl;  return 0;  
}

在这个例子中,serialize函数将Person对象的状态(age和name)写入一个输出流。deserialize函数从输入流中读取数据并恢复对象的状态。我们重载了<<和>>运算符来方便地使用这些函数。

注意:

序列化和反序列化应该是类的私有成员函数,通常通过友元函数或友元类来允许外部访问。
上述实现假设std::string的内部表示是连续的,这在许多实现中都是真的,但不是标准保证的。在更健壮的实现中,你应该使用固定大小的字符数组来存储字符串,或者将字符串长度作为序列化数据的一部分。
对于更复杂的类或包含循环引用的类,序列化和反序列化可能会更加复杂。
使用第三方库(如Boost.Serialization)可以简化这个过程,并提供更健壮和灵活的解决方案。
此外,对于文本序列化,你可能希望使用如JSON或XML等标准格式,这样可以在不同平台和语言之间更容易地交换数据。在这种情况下,你可能会使用像RapidJSON、nlohmann/json或TinyXML2这样的库来帮助处理序列化和反序列化。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/687226.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SG3225EAN规格书

SG3225EAN 晶体振荡器利用先进的锁相环技术和AT切割晶体单元&#xff0c;提供了宽频率范围和高性能LV-PECL输出&#xff0c;73.5 MHz至700 MHz的宽频率范围&#xff0c;能够保证高稳定性和宽频率调整的能力&#xff0c;适应于多样化的应用需求。2.5V和3.3V两种供电电压&#xf…

win10 环境下Python 3.8按装fastapi paddlepaddle 进行图片文字识别1

###按装 用conda 创建python 3.8的环境&#xff0c;可参看本人python下的其它文章。 在pycharm开发环境下按装相关的模块&#xff1a; pip install -i https://pypi.tuna.tsinghua.edu.cn/simple fastapi pip install -i https://pypi.tuna.tsinghua.edu.cn/simple "uvi…

StarRocks表设计——分区分桶与副本数

目录 一、数据分布 1.1 概述 1.2 数据分布方式 1.2.1 Round-Robin 1.2.2 Range 1.2.3 List 1.2.4 Hash 1.3 StarRocks的数据分布方式 1.3.1 不分区 Hash分桶 1.3.2 Range分区Hash分桶 三、分区 3.1 分区概述 3.2 创建分区 3.2.1 手动创建分区 3.2.2 批量创建分区…

【教学类-19-10】20240214《ABAB式-规律黏贴18格-手工纸15*15CM-一页3种图案,AB一组样板,纵向、有边框》(中班)

背景需求 利用15*15CM手工纸制作AB色块手环&#xff08;手工纸自带色彩&#xff09;&#xff0c;一页3个图案&#xff0c;2条为一组&#xff0c;画图案&#xff0c;黏贴成一个手环。 素材准备 代码展示 # # 作者&#xff1a;阿夏 # 时间&#xff1a;2024年2月14日 # 名称&…

云计算基础 -NUMA

UMA UMA中文翻译叫&#xff1a;一致性内存访问 多个CPU通过同一根前端总线&#xff08;FSB&#xff09;来访问内存&#xff08;所有的内存访问都需要通过北桥芯片来完成&#xff09;&#xff0c;若多个CPU访问内存的不同内存单元还是相同内存单元&#xff0c;同一时刻&#x…

[dlib][python]dlib所有whl文件下载地址汇总

python3.12轮子dlib-19.24.2-cp312-cp312-macosx-10-9-x86-64.whl下载地址 https://download.csdn.net/download/FL1623863129/88582377 python3.12轮子dlib-19.24.2-cp312-cp312-macosx-11-0-arm64.whl下载地址 https://download.csdn.net/download/FL1623863129/88582372 pyt…

机器学习中的10种非线性降维技术对比总结

降维意味着我们在不丢失太多信息的情况下减少数据集中的特征数量&#xff0c;降维算法属于无监督学习的范畴&#xff0c;用未标记的数据训练算法。 尽管降维方法种类繁多&#xff0c;但它们都可以归为两大类:线性和非线性。 线性方法将数据从高维空间线性投影到低维空间(因此…

计算机设计大赛 深度学习YOLO抽烟行为检测 - python opencv

文章目录 1 前言1 课题背景2 实现效果3 Yolov5算法3.1 简介3.2 相关技术 4 数据集处理及实验5 部分核心代码6 最后 1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 基于深度学习YOLO抽烟行为检测 该项目较为新颖&#xff0c;适合作为竞赛课…

多线程---线程同步,线程通信

线程同步 1.概述 线程同步是多线程编程中的一个重要概念&#xff0c;它指的是在多线程环境中&#xff0c;通过一定的机制保证多个线程按照某种特定的方式正确、有序地执行。这主要是为了避免并发问题&#xff0c;如死锁、竞态条件、资源争用等&#xff0c;确保数据的一致性和完…

Leetcode-1523. 在区间范围内统计奇数数目

题目&#xff1a; 给你两个非负整数 low 和 high 。请你返回 low 和 high 之间&#xff08;包括二者&#xff09;奇数的数目。 示例 1&#xff1a; 输入&#xff1a;low 3, high 7 输出&#xff1a;3 解释&#xff1a;3 到 7 之间奇数数字为 [3,5,7] 。 示例 2&#xff1a; 输…

中国电子学会2023年09月真题C语言软件编程等级考试一级(含解析答案)

中国电子学会考评中心历届真题&#xff08;含解析答案&#xff09; C语言软件编程等级考试一级 2023年09月 编程题五道 总分:100分一、日期输出&#xff08;20分&#xff09; 给定两个整数&#xff0c;表示一个日期的月和日。请按照“MM-DD”的格式输出日期&#xff0c…

【Java基础面试题】

目录 前言 1.1 为什么Java代码可以实现一次编写、到处运行&#xff1f; 1.2 一个Java文件里可以有多个类吗&#xff08;不含内部类&#xff09;&#xff1f; 1.3 说一说你对Java访问权限的了解 1.4 介绍一下Java的数据类型 1.5 int类型的数据范围是多少&#xff1f; 1.6…

C#入门及进阶|数组和集合(十):Queue类

在某种线性表中&#xff0c;需要加入的元素总是插入到线性表的末端&#xff0c;且总是从线性表的头部取出或删除元素&#xff0c;我们把这种线性表称为队列。 在C#中&#xff0c;通过Queue集合来封装对队列的操作&#xff0c;在队列中对元素的操作遵循“先进先出”的原则。Queu…

【算法】问题描述关键提取——提炼一般的解决思路

文章目录 前言排序关键/关键词2389. 和有限的最长子序列 栈关键/关键词2390. 从字符串中移除星号 拓扑排序关键/关键词207. 课程表2392. 给定条件下构造矩阵 线性DP关键/关键词最长公共子序列1143. 最长公共子序列 最长递增子序列300. 最长递增子序列与最长公共子序列的联系动态…

【复现】某公司指挥调度管理平台 RCE漏洞_51

目录 一.概述 二 .漏洞影响 三.漏洞复现 1. 漏洞一&#xff1a; 四.修复建议&#xff1a; 五. 搜索语法&#xff1a; 六.免责声明 一.概述 该平台提供强大的指挥调度功能&#xff0c;可以实时监控和管理通信网络设备、维护人员和工作任务等。用户可以通过该平台发送指令…

P1441 背包九讲(3):完全背包问题

P1441 背包九讲3&#xff1a;完全背包问题 一、原题呈现1、题目描述2、输入描述3、输出描述4、样例输入5、样例输出6、提示信息 二、思路分析1、其实这题就是01背包的变形2、但是本题全开二维数组会超内存&#xff0c;因此我们使用两个一维数组进行计算并且复制 三、整体代码 一…

视频生成模型作为世界模拟器

我们探索了在视频数据上大规模训练生成模型。具体来说&#xff0c;我们联合训练文本条件扩散模型&#xff0c;处理不同持续时间、分辨率和宽高比的视频和图像。我们利用一种在时空补丁上操作视频和图像潜码的transformer架构。我们最大的模型&#xff0c;Sora&#xff0c;能够生…

树状菜单(利用映射-bootstrap+jQuery实现折叠功能)

效果&#xff08;默认全部展开&#xff09;&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><…

CSS的background 背景图片自动适应元素大小,实现img的默认效果 background-size:100% 100%;

CSS的background 背景图片自动适应元素大小,实现img的默认效果 background-size:100% 100%; 关键是background-size:100% 100%; background-size:100% 100%; background-size:100% 100%; background-size:contain; 保持纵横比, 容器部分可能空白background-size:cover; 保…

解锁Spring Boot中的设计模式—02.解释器模式:探索【解释器模式】的奥秘与应用实践!

解释器模式 1.简介 解释器模式&#xff08;Interpreter Pattern&#xff09;是一种行为设计模式&#xff0c;它用于定义语言的文法&#xff0c;并且解释语言中的表达式。在Java中&#xff0c;解释器模式可以用于构建解释器以解析特定的语言或表达式&#xff0c;如数学表达式、…