目录
  • 浅拷贝
    • 结构体中不存在指针成员变量时
    • 结构体中存在指针成员变量时
  • 深拷贝
    • 结论

      浅拷贝

      C语言中的浅拷贝是指在拷贝过程中,对于指针型成员变量只拷贝指针本身,而不拷贝指针所指向的目标,它按字节复制的。我们分几种情况举例子来看一下。

      结构体中不存在指针成员变量时

      代码如下:

      #include <stdio.h>
      typedef struct {
          char name[64];
          int age;
      }Member;
       
      int main(){
          Member stu1 = { "LiMing", 18 };
          Member stu2;
          stu2 = stu1;
          printf("%s,%d\n", stu2.name, stu2.age);
          system("pause");
          return 0;
      }
      

      运行如下:

      C语言结构体成员赋值的深拷贝与浅拷贝详解

      结构体中存在指针成员变量时

      代码如下:

      #include <stdio.h>
      #include <stdlib.h>
      #include <string.h>
       
      typedef struct {
       char *name;
       int age;
      }Member;
       
      int main() {
       Member Member1, Member2;
       Member1.name = malloc(sizeof(char) * 64);
       if (NULL == Member1.name)
       {
        printf("malloc failed\n");
       }
       memset(Member1.name, 0, 64);
       //strcpy(Member1.name, "LiMing");
       snprintf(Member1.name, 64, "LiMing");
       Member1.age = 18;
       
       Member2 = Member1;/*拷贝*/
       snprintf(Member2.name, 64, "LiXiaoYao");
       Member2.age = 29;
       
       printf("%s, %d\n", Member1.name, Member1.age);
       
       if (NULL != Member1.name) {
        free(Member1.name);
        Member1.name = NULL;
       }
       
       system("pause");
       return 0;
      }

      运行如下:

      C语言结构体成员赋值的深拷贝与浅拷贝详解

      从中我们看到,改变Member2的值,Member1的值也改变了,这说明一片空间被两个不同的子对象共享了,改变一个对象的值另外一个也会随之改变。

      我们改变Member2写法,申请内存的代码如下:

      #include <stdio.h>
      #include <stdlib.h>
      #include <string.h>
       
      typedef struct {
       char *name;
       int age;
      }Member;
       
      int main() {
       Member Member1;
       Member1.name = malloc(sizeof(char) * 64);
       if (NULL == Member1.name)
       {
        printf("malloc failed\n");
       }
       memset(Member1.name, 0, 64);
       //strcpy(Member1.name, "LiMing");
       snprintf(Member1.name, 64, "LiMing");
       Member1.age = 18;
        
        Member Member2;
       Member2.name = malloc(sizeof(char) * 64);
       if (NULL == Member2.name)
       {
        printf("malloc failed\n");
       }
       memset(Member2.name, 0, 64);
       //strcpy(Member2.name, "LiMing");
       snprintf(Member2.name, 64, "LiXiaoYao");
       Member2.age = 29;
       
       Member1 = Member2;
       
       printf("%s, %d\n", Member2.name, Member2.age);
       
       if (NULL != Member1.name) {
        free(Member1.name);
        Member1.name = NULL;
       }
       if (NULL != Member2.name) {
        free(Member2.name);
        Member2.name = NULL;
       }
       system("pause");
       return 0;
      }

      运行如下:

      C语言结构体成员赋值的深拷贝与浅拷贝详解

      从中我们看到,当数据成员中有指针时,两个类中的两个指针将指向同一个地址,当对象快结束时,会调用两次free函数,此时Member2已经是野指针(图中有X的错误标志),这个野指针指向的内存空间已经被释放掉,再次释放会报异常错误,要解决这个问题就要涉及到深拷贝了。

      深拷贝

      深拷贝除了拷贝其成员本身的值之外,还拷贝成员指向的动态内存区域内容,深拷贝会在堆内存中另外申请空间来储存数据。

      解决的思路是在释放掉被赋值指针变量的旧指向内存时,重新对其开辟新内存,这种情况下两个结构体中指针地址不同,但是指向的内容是一致的。代码如下:

      #include <stdio.h>
      #include <stdlib.h>
       
      typedef struct {
       char *name;
       int age;
      }Member;
       
      int main() {
       Member Member1;
       Member1.name = malloc(sizeof(char) * 64);
       if (NULL == Member1.name)
       {
        printf("malloc failed\n");
       }
       memset(Member1.name, 0, 64);
       //strcpy(Member1.name, "LiMing");
       snprintf(Member1.name, 64, "LiMing");
       Member1.age = 18;
       
        Member Member2;
       Member2.name = malloc(sizeof(char) * 64);
       if (NULL == Member2.name)
       {
        printf("malloc failed\n");
       }
       memset(Member2.name, 0, 64);
       //strcpy(Member2.name, "LiMing");
       snprintf(Member2.name, 64, "LiXiaoYao");
       Member2.age = 29;
       
       if (Member1.name != NULL) {
        free(Member1.name);
        Member1.name = NULL;
       }
       Member1.name = malloc(strlen(Member2.name) + 1);
       strcpy(Member1.name, Member2.name);
       
       printf("%s, %d\n", Member1.name, Member1.age);
       
       if (NULL != Member1.name) {
        free(Member1.name);
        Member1.name = NULL;
       }
       if (NULL != Member2.name) {
        free(Member2.name);
        Member2.name = NULL;
       }
       system("pause");
       return 0;
      }

      运行如下:

      C语言结构体成员赋值的深拷贝与浅拷贝详解

      结论

      使用C语言来说,深拷贝浅拷贝的概念我们不需要深究,在进行结构体拷贝的时候,结构体成员是非指针的话,那么直接赋值是没有任何问题的,建议使用这种方式,避免浅拷贝这类不易发现的错误产生。

      如果成员有指针类型,我们就需要重写拷贝函数,自己定义拷贝行为了,这一点我们需要尤为注意。

      声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。