如何理解结构体的浅拷贝与深拷贝

本文涉及的产品
实时计算 Flink 版,5000CU*H 3个月
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
实时数仓Hologres,5000CU*H 100GB 3个月
简介: 结构体的浅拷贝仅复制对象的引用或基本数据类型值,不创建新对象;深拷贝则会递归地复制所有对象及其引用的对象,形成完全独立的新对象。两者主要区别在于是否共享内部对象。
  1. 浅拷贝(Shallow Copy)

    • 定义:浅拷贝是指在拷贝一个结构体时,只是简单地复制结构体中的成员的值。如果结构体的成员包含指针,那么浅拷贝只是复制指针的值,而不是指针所指向的数据。这意味着原始结构体和拷贝后的结构体中的指针成员将指向相同的内存地址。
    • 示例

      #include <stdio.h>
      #include <stdlib.h>
      
      struct MyStruct {
             
          int num;
          int *ptr;
      };
      
      int main() {
             
          struct MyStruct original;
          original.num = 10;
          original.ptr = (int *)malloc(sizeof(int));
          *original.ptr = 20;
      
          struct MyStruct copy = original;
          // 浅拷贝后,copy.ptr和original.ptr指向相同的内存地址
          printf("original.ptr points to %p and copy.ptr points to %p\n", original.ptr, copy.ptr);
          // 修改copy中的数据
          copy.num = 30;
          *copy.ptr = 40;
          // 观察original中的数据变化
          printf("original.num = %d, *original.ptr = %d\n", original.num, *original.ptr);
          free(original.ptr);
          return 0;
      }
      
    • 解释
      • 在这个示例中,定义了一个包含一个整数成员num和一个整数指针成员ptr的结构体MyStruct。首先初始化original结构体,为ptr成员分配内存并赋值。
      • 当进行struct MyStruct copy = original;这一浅拷贝操作时,copy结构体的num成员获得了original.num的值,而copy.ptr获得了original.ptr的值,也就是它们指向了同一块动态分配的内存。
      • 当修改copy.num时,original.num不受影响,因为它们是独立的整数。但是当修改*copy.ptr时,*original.ptr也会改变,因为它们指向相同的内存位置。
      • 最后,只需要释放original.ptr所指向的内存即可,因为copy.ptr指向的是同一块内存。不过这种共享内存的方式可能会导致问题,比如其中一个结构体释放了指针所指向的内存,另一个结构体再访问该指针就会出现错误(悬空指针)。
  2. 深拷贝(Deep Copy)

    • 定义:深拷贝是指在拷贝一个结构体时,不仅复制结构体中的成员的值,还会复制指针成员所指向的数据。这会创建全新的内存空间来存储数据,使得原始结构体和拷贝后的结构体完全独立,对其中一个结构体的修改不会影响到另一个结构体。
    • 示例

      #include <stdio.h>
      #include <stdlib.h>
      
      struct MyStruct {
             
          int num;
          int *ptr;
      };
      
      void deepCopy(struct MyStruct *dest, const struct MyStruct *src) {
             
          dest->num = src->num;
          dest->ptr = (int *)malloc(sizeof(int));
          *dest->ptr = *src->ptr;
      }
      
      int main() {
             
          struct MyStruct original;
          original.num = 10;
          original.ptr = (int *)malloc(sizeof(int));
          *original.ptr = 20;
      
          struct MyStruct copy;
          deepCopy(&copy, &original);
          // 深拷贝后,copy.ptr和original.ptr指向不同的内存地址
          printf("original.ptr points to %p and copy.ptr points to %p\n", original.ptr, copy.ptr);
          // 修改copy中的数据
          copy.num = 30;
          *copy.ptr = 40;
          // 观察original中的数据变化
          printf("original.num = %d, *original.ptr = %d\n", original.num, *original.ptr);
          free(original.ptr);
          free(copy.ptr);
          return 0;
      }
      
    • 解释
      • 在这个示例中,定义了一个函数deepCopy来实现深拷贝。函数接受两个结构体指针,dest为目标结构体指针,src为源结构体指针。
      • deepCopy函数中,首先复制src结构体的num成员的值到dest结构体的num成员。然后为dest结构体的ptr成员分配新的内存空间,并且将src.ptr所指向的数据复制到dest.ptr所指向的新内存空间中。
      • main函数中,通过deepCopy函数进行深拷贝。之后可以看到original.ptrcopy.ptr指向不同的内存地址。
      • 当修改copy结构体中的成员时,original结构体中的成员不会受到影响,因为它们的数据是相互独立的。最后,需要分别释放original.ptrcopy.ptr所指向的内存,以避免内存泄漏。

总的来说,浅拷贝和深拷贝的主要区别在于对指针成员的处理方式。浅拷贝只是简单地复制指针的值,而深拷贝会复制指针所指向的数据,使得两个结构体在内存使用上更加独立。在实际编程中,需要根据具体的需求来选择合适的拷贝方式。如果结构体中的成员没有指针,浅拷贝和深拷贝的效果是一样的。但如果包含指针,就需要谨慎考虑,避免出现悬空指针、内存泄漏等问题。

相关文章
|
6月前
|
存储 人工智能 前端开发
深拷贝浅拷贝的区别?如何实现一个深拷贝?
深拷贝浅拷贝的区别?如何实现一个深拷贝?
101 0
|
6天前
|
存储 C语言
如何在 C 语言中实现结构体的深拷贝
在C语言中实现结构体的深拷贝,需要手动分配内存并逐个复制成员变量,确保新结构体与原结构体完全独立,避免浅拷贝导致的数据共享问题。具体方法包括使用 `malloc` 分配内存和 `memcpy` 或手动赋值。
22 10
|
18天前
|
存储 前端开发 JavaScript
浅拷贝和深拷贝的区别?
本文首发于微信公众号“前端徐徐”,介绍了JavaScript中浅拷贝和深拷贝的概念及其实现方法。文章首先解释了数据类型的基础,包括原始值和对象的区别,然后详细介绍了浅拷贝和深拷贝的定义、底层逻辑以及常见的实现方式,如 `Object.assign`、扩展运算符、`JSON.stringify` 和手动实现等。最后,通过对比浅拷贝和深拷贝的区别,帮助读者更好地理解和应用这两种拷贝方式。
26 0
浅拷贝和深拷贝的区别?
|
5月前
|
安全 Java
深拷贝和浅拷贝的区别
深拷贝和浅拷贝的区别
|
6月前
|
C++
C++什么是深浅拷贝,深浅拷贝的区别?
C++什么是深浅拷贝,深浅拷贝的区别?
|
人工智能 JavaScript 前端开发
为什么要用深浅拷贝、什么是深浅拷贝、以及如何实现
首先我们要明白一点,js中数据类型分为: 基本数据类型 (Number, String, Boolean, Null, Undefined, Symbol) 对象数据类型 ( Object )** 引用数据类型的值是保存在栈内存和堆内存中的对象。栈区内存保存变量标识符和指向堆内存中该对象的指针。当寻找引用值时,解释器会先寻找栈中的地址。然后根据地址找到堆内存的实体
109 0
为什么要用深浅拷贝、什么是深浅拷贝、以及如何实现
|
存储 JavaScript 前端开发
深拷贝浅拷贝有什么区别?怎么实现深拷贝?
深拷贝浅拷贝有什么区别?怎么实现深拷贝?
91 0
|
JSON 数据格式
深拷贝和浅拷贝、及实现方式
深拷贝和浅拷贝、及实现方式
94 0
|
C++
C++类与对象中深拷贝与浅拷贝
C++类与对象中深拷贝与浅拷贝
65 0