c/c++ 深拷贝和浅拷贝

深拷贝与浅拷贝

深拷贝(Deep Copy)和浅拷贝(Shallow Copy)是对象复制的两种不同方式,它们涉及到对象成员数据的复制方式和内存管理。

  • 浅拷贝(Shallow Copy):
    浅拷贝是指将一个对象的成员值简单地复制到另一个对象,包括指针类型的成员变量。浅拷贝只复制指针的值,而不会为指针指向的数据分配新的内存空间。这意味着原始对象和副本对象将共享同一份数据。如果其中一个对象修改了共享的数据,将影响到其他对象。
    在这里插入图片描述

  • 深拷贝(Deep Copy):
    深拷贝是指复制对象的每个成员,包括指针类型的成员变量。深拷贝会为每个指针类型的成员变量分配独立的内存空间,并将原始对象指针指向的数据复制到新分配的内存中。这样,原始对象和副本对象拥有各自独立的数据副本,对其中一个对象的修改不会影响到其他对象。
    在这里插入图片描述

  • 深拷贝和浅拷贝的选择取决于对象的成员数据类型和应用场景。对于简单的数据类型或者不涉及动态内存分配的对象,浅拷贝可能足够满足需求。但对于包含指针类型成员或动态分配内存的对象,通常需要使用深拷贝来确保对象之间的独立性。

  • 在C++中,可以通过自定义拷贝构造函数、赋值运算符重载或使用智能指针等方式来实现深拷贝。C语言中需要手动进行内存分配和复制操作,通过手动分配内存、复制数据并管理内存释放来实现深拷贝。

c语言深拷贝和浅拷贝

在C 语言中,没有像 C++ 中那样提供内置的深拷贝和浅拷贝的机制。在 C 语言中,需要手动编写代码来实现深拷贝和浅拷贝。

  • 浅拷贝(Shallow Copy):
    在 C 语言中,浅拷贝可以通过简单地将一个结构体或数组的成员值赋值给另一个结构体或数组来实现。这将导致两个对象共享相同的内存数据,包括指针类型的成员变量。如果其中一个对象修改了共享的数据,将影响到其他对象。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>typedef struct {char* name;int age;
} Person;int main() {Person person1;person1.name = malloc(sizeof(char) * 10);strcpy(person1.name, "John");person1.age = 25;Person person2 = person1;  // 浅拷贝// 修改 person2 的值person2.name = malloc(sizeof(char) * 10);strcpy(person2.name, "Alice");person2.age = 30;// 输出 person1 和 person2 的值printf("person1: name=%s, age=%d\n", person1.name, person1.age);printf("person2: name=%s, age=%d\n", person2.name, person2.age);// 释放内存free(person1.name);free(person2.name);return 0;
}

在上述示例中,通过将 person1 的成员值赋值给 person2,实现了浅拷贝。由于两个对象共享相同的内存数据,对其中一个对象的修改会影响另一个对象。

  • 深拷贝(Deep Copy):
    在 C 语言中,深拷贝需要手动进行内存分配和数据复制。对于包含指针类型成员变量的结构体或数组,需要为每个指针类型的成员变量分配独立的内存空间,并将原始对象指针指向的数据复制到新分配的内存中。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>typedef struct {char* name;int age;
} Person;// 深拷贝的函数
void deepCopyPerson(Person* dest, const Person* src) {dest->name = malloc(sizeof(char) * (strlen(src->name) + 1));strcpy(dest->name, src->name);dest->age = src->age;
}int main() {Person person1;person1.name = malloc(sizeof(char) * 10);strcpy(person1.name, "John");person1.age = 25;Person person2;deepCopyPerson(&person2, &person1);  // 深拷贝// 修改 person2 的值free(person2.name);person2.name = malloc(sizeof(char) * 10);strcpy(person2.name, "Alice");person2.age = 30;// 输出 person1 和 person2 的值printf("person1: name=%s, age=%d\n", person1.name, person1.age);printf("person2: name=%s, age=%d\n", person2.name, person2.age);// 释放内存free(person1.name);free(person2.name);return 0;
}

在上述示例中,通过自定义的函数 deepCopyPerson,实现了深拷贝。该函数手动为 person2 的成员变量分配独立的内存,并将原始对象的数据复制到新分配的内存中。这样,原始对象和副本对象拥有各自独立的数据副本。在使用完后,还需要手动释放内存。

c++深拷贝和浅拷贝

在 C++ 中,可以通过拷贝构造函数赋值运算符来实现深拷贝和浅拷贝。

  • 浅拷贝(Shallow Copy):
    (1)默认情况下,C++ 提供的拷贝构造函数和赋值运算符执行的是浅拷贝操作,即简单地复制成员变量的值。
    (2)对于指针类型的成员变量,直接复制指针的值,这样两个对象将共享相同的内存数据。
class ShallowCopy {
public:ShallowCopy(int* data, int size) {this->data = data;this->size = size;}// 默认拷贝构造函数执行浅拷贝ShallowCopy(const ShallowCopy& other) {data = other.data;  // 复制指针的值size = other.size;}// 默认赋值运算符执行浅拷贝ShallowCopy& operator=(const ShallowCopy& other) {if (this != &other) {data = other.data;  // 复制指针的值size = other.size;}return *this;}private:int* data;int size;
};

在上述示例中,ShallowCopy 类具有一个指针类型的成员变量 data 和一个整数 size。默认的拷贝构造函数和赋值运算符执行浅拷贝,直接复制指针的值,这样两个对象将共享相同的数据。

  • 深拷贝(Deep Copy):
    (1)在自定义拷贝构造函数和赋值运算符时,先为新对象分配独立的内存空间。
    (2)将原始对象的数据复制到新的内存空间中,确保每个对象拥有独立的数据副本。
class DeepCopy {
public:DeepCopy(int* data, int size) {this->data = new int[size];for (int i = 0; i < size; ++i) {this->data[i] = data[i];}this->size = size;}// 自定义拷贝构造函数执行深拷贝DeepCopy(const DeepCopy& other) {data = new int[other.size];for (int i = 0; i < other.size; ++i) {data[i] = other.data[i];}size = other.size;}// 自定义赋值运算符执行深拷贝DeepCopy& operator=(const DeepCopy& other) {if (this != &other) {delete[] data;data = new int[other.size];for (int i = 0; i < other.size; ++i) {data[i] = other.data[i];}size = other.size;}return *this;}~DeepCopy() {delete[] data;}private:int* data;int size;
};

在上述示例中,DeepCopy 类具有一个指针类型的成员变量 data 和一个整数 size。自定义的拷贝构造函数和赋值运算符执行深拷贝,为新对象分配独立的内存空间,并将原始对象的数据复制到新的内存空间中,确保每个对象拥有独立的数据副本。

需要注意的是,在自定义拷贝构造函数和赋值运算符时,还需要注意内存管理,确保在对象销毁时释放已分配的内存,以避免内存泄漏。在示例中,通过在析构函数中释放 data 数组所占用的内存。

参考

  • AI。

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

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

相关文章

C++:继承:面向对象编程的重要特性

(❁◡❁)(●◡●)╰(*▽*)╯(*/ω&#xff3c;*)(^///^)(❁◡❁)(❁◡❁)(●◡●)╰(*▽*)╯(*/ω&#xff3c;*)(❁◡❁)(●’◡’●)╰(▽)╯(/ω&#xff3c;)(///) C&#xff1a;继承&#xff1a;面向对象编程的重要特性 前言**继承**1.继承的概念及定义1.1继承的概念1.2继…

算法笔记p251队列循环队列

目录 队列循环队列循环队列的定义初始化判空判满入队出队获取队列内元素的个数取队首元素取队尾元素 队列 队列是一种先进先出的数据结构&#xff0c;总是从队尾加入元素&#xff0c;从队首移除元素&#xff0c;满足先进先出的原则。队列的常用操作包括获取队列内元素的个数&a…

【Godot4.2】颜色完全使用手册

概述 本篇简单汇总Godot中的颜色的构造和使用&#xff0c;内容包括了&#xff1a; RGB、RGBA&#xff0c;HSV以及HTML16进制颜色值、颜色常量等形式构造颜色颜色的运算以及取反、插值用类型化数组、紧缩数组或PNG图片形式存储多个颜色 构造颜色 因为颜色是一种视觉元素&…

Jmeter接口测试步骤

一、使用工具测试 1、使用Jmeter对接口测试 首先我们说一下为什么用Posman测试后我们还要用Jmeter做接口测试&#xff0c;在用posman测试时候会发现的是一个接口一个接口的测试&#xff0c;我们每次测试成功后的数据&#xff0c;在工具中是无法保存的&#xff0c;再次测试的时…

【蓝桥杯入门记录】继电器、蜂鸣器及原理图分析

一、继电器、继电器概述 &#xff08;1&#xff09;蜂鸣器原理 蜂鸣器的发声原理由振动装置和谐振装置组成&#xff0c;而蜂鸣器又分为无源他激型与有源自激型&#xff0c;蜂鸣器的发声原理为: 1、无源他激型蜂鸣器的工作发声原理是&#xff1a;方波信号输入谐振装置转换为声…

Vue.js开发基础

单文件组件 使用Vite创建Vue项目后&#xff0c;目录结构中包含一些扩展名为.vue的文件&#xff0c;每个.vue文件都可用来定义一个单文件组件。Vue中的单文件组件是Vue组件的文件格式。每个单文件组件由模板、样式和逻辑3个部分构成。 运行结果&#xff1a; 1.模板 模板用于搭建…

PyTorch 深度学习(GPT 重译)(一)

第一部分&#xff1a;PyTorch 核心 欢迎来到本书的第一部分。在这里&#xff0c;我们将与 PyTorch 迈出第一步&#xff0c;获得理解其结构和解决 PyTorch 项目机制所需的基本技能。 在第一章中&#xff0c;我们将首次接触 PyTorch&#xff0c;了解它是什么&#xff0c;解决了…

爬虫基础:HTTP基本原理

爬虫基础&#xff1a;HTTP基本原理 前言HTTP基本原理URI 和 URLHTTP 和 HTTPSHTTP 请求过程请求与响应HTTP请求HTTP响应请求与响应的交互过程 HTTP 2.0二进制传输多路复用Header压缩服务器端提前响应内容安全 前言 了解 HTTP的基本原理&#xff0c;了解从往测览器中输人 URL到获…

算法沉淀——贪心算法四(leetcode真题剖析)

算法沉淀——贪心算法四 01.最长回文串02.增减字符串匹配03.分发饼干04.最优除法 01.最长回文串 题目链接&#xff1a;https://leetcode.cn/problems/longest-palindrome/ 给定一个包含大写字母和小写字母的字符串 s &#xff0c;返回 通过这些字母构造成的 最长的回文串 。 …

YOLOV5 改进:修改网络结构--C2f 模块

1、前言 YOLOV5 采用C3模块,类似于残差结构的思想 class C3(nn.Module):# CSP Bottleneck with 3 convolutionsdef __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5): # ch_in, ch_out, number, shortcut, groups, expansionsuper().__init__()c_ = int(c2 * e) #…

Linux中,运行程序,顺便将打印信息存储在Log文件中查看

前言 如题&#xff0c;原本打算在代码中自己写一个类去管理将打印信息收集到log日志中&#xff0c;忽然想到&#xff0c;其实也可以写sh脚本 简单demo1 #!/bin/bash# 启动应用程序 test&#xff0c;并将标准输出和标准错误输出都追加到 log 文件中 ./test >> output.log…

7-7 12-24小时制

题目链接&#xff1a;7-7 12-24小时制 一. 题目 1. 题目 2. 输入输出格式 3. 输入输出样例 4. 限制 二、代码 1. 代码实现 #include <stdio.h>int main(void) {int hour, minute;char *str;if (scanf("%d:%d", &hour, &minute) ! 2) {return -1;}i…

操作系统系列学习——死锁处理

文章目录 前言死锁处理 前言 一个本硕双非的小菜鸡&#xff0c;备战24年秋招&#xff0c;计划学习操作系统并完成6.0S81&#xff0c;加油&#xff01; 本文总结自B站【哈工大】操作系统 李治军&#xff08;全32讲&#xff09; 老师课程讲的非常好&#xff0c;感谢 【哈工大】操…

如何优惠申请DigiCert证书

DigiCert作为全球知名的数字证书颁发机构&#xff0c;其SSL证书以高度的安全性和信任度广受认可。而JoySSL作为国内优秀的SSL证书服务平台&#xff0c;提供了便捷、高效的证书申请服务&#xff0c;让您能够轻松获取并安装DigiCert SSL证书。接下来&#xff0c;本文将详细介绍如…

什么情况用@RequestBody、@RequestParm、@PathVariable

1.requestParam(请求参数&#xff09;&#xff1a;使用RequestParam注释将请求参数绑定到控制器中的方法参数。用于从请求访问查询参数值的RequestParam注释。 如下请求URL&#xff1a;http://localhost:8080/springmvc/hello/101?param110&param220 以下是RequestParam注…

腾讯云服务器怎么买省钱?先领券,再下单!

腾讯云代金券领取渠道有哪些&#xff1f;腾讯云官网可以领取、官方媒体账号可以领取代金券、完成任务可以领取代金券&#xff0c;大家也可以在腾讯云百科蹲守代金券&#xff0c;因为腾讯云代金券领取渠道比较分散&#xff0c;腾讯云百科txybk.com专注汇总优惠代金券领取页面&am…

网工内推 | 七险一金,上市公司招信息安全工程师,大牛带队

01 启明星辰信息技术集团股份有限公司 招聘岗位&#xff1a;数据安全服务工程师 职责描述&#xff1a; 1、负责数据安全服务项目的管理&#xff0c;统筹组织并协调资源落实项目交付实施; 3、负责数据安全风险评估、数据分类分级、数据安全管理制度、数据安全体系规划等数据安…

企事业单位宣传,三下乡的稿子怎么在学习强国网投稿发稿,价格多少钱?

随着学习强国成为各个企事业单位宣传的重要平台&#xff0c;如何在学习强国上发稿&#xff0c;尤其是三下乡的宣传稿件&#xff0c;成为了各位传媒工作者关注的焦点。在这里&#xff0c;我们要向大家介绍一下媒介多多网发稿平台&#xff0c;为大家提供一个便捷高效的投稿发稿渠…

STM32相关资料汇总

STM32选型表 STM32手册参考网站 https://www.stmcu.org.cn/

命名空间——初识c++

. 个人主页&#xff1a;晓风飞 专栏&#xff1a;数据结构|Linux|C语言 路漫漫其修远兮&#xff0c;吾将上下而求索 文章目录 经典的Hello Word 起航c关键字c语言的命名冲突问题域作用限定符::命名空间 namespace命名空间定义命名空间的使用1.加命名空间名称及作用域限定符2.使用…