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

用C语言实现原型模式时,如何确定需要深拷贝还是浅拷贝?

在C语言实现原型模式时,深拷贝(Deep Copy)浅拷贝(Shallow Copy) 的选择取决于原型对象中成员的类型(尤其是是否包含动态分配的内存)。核心原则是:确保克隆对象的独立性——修改克隆对象不会影响原对象,反之亦然

1. 浅拷贝(Shallow Copy)的适用场景

浅拷贝仅复制对象的“表面”成员(直接赋值),不复制成员指向的动态内存。适用于:

  • 所有成员都是基本数据类型intfloatchar等)。
  • 成员中没有动态分配的内存(如malloc分配的指针)。
示例:纯基本类型的结构体(适合浅拷贝)
typedef struct {int id;float value;char flag;
} SimpleData;// 浅拷贝实现(直接 memcpy)
SimpleData* shallow_copy(SimpleData* orig) {SimpleData* copy = malloc(sizeof(SimpleData));if (copy) {*copy = *orig; // 直接赋值所有成员(浅拷贝)}return copy;
}

原因:所有成员都是基本类型,存储在结构体内部,复制后克隆对象与原对象的成员互不干扰。

2. 深拷贝(Deep Copy)的适用场景

深拷贝不仅复制对象本身,还会递归复制对象中所有动态分配的内存(如指针指向的堆内存、数组、嵌套结构体等)。适用于:

  • 成员包含指针,且指针指向动态分配的内存(如char*字符串、int*数组)。
  • 成员包含嵌套结构体,且嵌套结构体中包含动态内存。
示例:含动态字符串的结构体(必须深拷贝)
typedef struct {char* name; // 动态分配的字符串(需深拷贝)int age;
} Person;// 深拷贝实现(复制指针指向的内存)
Person* deep_copy(Person* orig) {Person* copy = malloc(sizeof(Person));if (!copy) return NULL;// 1. 复制基本类型(浅拷贝部分)copy->age = orig->age;// 2. 深拷贝动态字符串(关键步骤)if (orig->name) {// 为克隆对象的name分配新内存,并复制内容copy->name = malloc(strlen(orig->name) + 1);if (copy->name) {strcpy(copy->name, orig->name);} else {free(copy);return NULL;}} else {copy->name = NULL;}return copy;
}

原因:如果对name仅做浅拷贝(copy->name = orig->name),则克隆对象与原对象的name指针会指向同一块内存。修改其中一个的name会影响另一个,违背“克隆对象独立”的原则。

3. 如何判断?—— 检查成员是否“拥有”动态内存

  • 若成员是“值类型”(基本类型、枚举、不含指针的结构体):浅拷贝即可。
  • 若成员是“引用类型”(指针指向堆内存、动态数组、文件句柄等):必须深拷贝,否则会导致“同一块内存被多个对象共享”,可能引发:
    • 重复释放(free同一块内存两次,导致崩溃)。
    • 无意修改(一个对象修改内容,另一个对象受影响)。

4. 混合场景:部分成员深拷贝,部分浅拷贝

实际开发中,对象可能同时包含基本类型和动态内存,此时需针对性处理

  • 基本类型:浅拷贝。
  • 动态内存指针:深拷贝。
示例:混合类型结构体的拷贝
typedef struct {int id;                  // 基本类型(浅拷贝)char* data;              // 动态字符串(深拷贝)int* scores;             // 动态数组(深拷贝)int score_count;         // 数组长度(浅拷贝)
} Student;Student* student_clone(Student* orig) {Student* copy = malloc(sizeof(Student));if (!copy) return NULL;// 浅拷贝基本类型copy->id = orig->id;copy->score_count = orig->score_count;// 深拷贝动态字符串if (orig->data) {copy->data = malloc(strlen(orig->data) + 1);strcpy(copy->data, orig->data);} else {copy->data = NULL;}// 深拷贝动态数组if (orig->scores && orig->score_count > 0) {copy->scores = malloc(sizeof(int) * orig->score_count);memcpy(copy->scores, orig->scores, sizeof(int) * orig->score_count);} else {copy->scores = NULL;}return copy;
}

总结:选择原则

场景拷贝方式核心操作
成员均为基本类型(无指针)浅拷贝直接赋值(*copy = *origmemcpy
成员包含动态内存指针(malloc分配)深拷贝为指针重新分配内存,并复制原内容
混合类型部分浅拷贝 + 部分深拷贝基本类型直接复制,动态内存指针单独深拷贝

本质:深拷贝的目的是让克隆对象与原对象完全独立,两者的内存空间没有重叠。在原型模式中,若克隆对象需要修改自身属性而不影响原型,必须根据成员类型正确选择拷贝方式。

http://www.dtcms.com/a/507261.html

相关文章:

  • Spring Boot 3零基础教程,WEB 开发 Thymeleaf 属性优先级 行内写法 变量选择 笔记42
  • Go语言:对其语法的一些见解
  • Go Web 编程快速入门 · 04 - 请求对象 Request:头、体与查询参数
  • 伦教九江网站建设辽宁工程建筑信息网
  • Deep End-to-End Alignment and Refinement for Time-of-Flight RGB-D Module,2019
  • Ubuntu 安装 Gitea
  • 通达信灵活屏
  • 亚马逊云代理商:AWS怎么通过加密实现数据保护目标?
  • C标准库--C99--控制浮点环境<fenv.h>
  • 【Linux】“ 权限 “ 与相关指令
  • webrtc弱网-ReceiveSideCongestionController类源码分析及算法原理
  • 通达信--主题投资分析
  • 揭阳专业做网站天台县建设规划局网站
  • 福海网站制作关键词堆砌的作弊网站
  • sql特训
  • LeetCode 刷题【126. 单词接龙 II】
  • 防火墙规则设置
  • 江协科技STM32课程笔记(五)— ADC模数转换器
  • 什么是慢查询,慢请求,以及如何避免
  • 网站设计模板简约福州网站设计
  • 各大网站做推广广告什么是企业形象设计
  • 大模型金融量化比赛
  • Kubernetes深入学习之容器入门(一)
  • Docker安装部署MrDoc觅思文档-免费的国产知识库管理系统
  • 批量更新操作全攻略:从JDBC原理到多框架实现(MyBatis/MyBatis-Plus/Nutz)
  • 简述:普瑞时空数据建库软件(国土变更建库)之一(2025年部分新规则)
  • 零基础新手小白快速了解掌握服务集群与自动化运维(十二)Python编程之面向对象
  • 刚学做网站怎么划算普洱专业企业网站建设
  • Java基础——面向对象复习知识点12
  • IPv6路由技术