C++ 的浅拷贝和深拷贝(结构体)

拷贝有两种:深拷贝,浅拷贝

浅拷贝:拷贝过程中是按字节复制的,对于指针型成员变量只复制指针本身,而不复制指针所指向的目标

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

 typedef struct {
char name[];
int age;
}Person; void test005(){ Person stu1 = { "aaa", };
Person stu2;
stu2 = stu1;
printf("%s,%d\n", stu2.name, stu2.age);
} int main(){
test005();
system("pause");
return ;
}

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

 typedef struct{
char *name;
int age;
} Tea; void test006(){
Tea teacher1, teacher2;
teacher1.name = malloc(sizeof(char)* );
memset(teacher1.name, , );
strcpy(teacher1.name, "aaaa");
teacher1.age = ; teacher2.name = malloc(sizeof(char)* );
memset(teacher2.name, , );
strcpy(teacher2.name, "bbbb");
teacher2.age = ; //结构体赋值
teacher1 = teacher2; printf("%s, %d\n", teacher2.name, teacher2.age); if (NULL != teacher1.name){
free(teacher1.name);
teacher1.name = NULL;
}
if (NULL != teacher2.name){
free(teacher2.name);
teacher2.name = NULL;
}
} int main(){
test006();
system("pause");
return ;
}

运行该结构体赋值,出现报错:

浅拷贝存在的问题:当出现类的等号赋值时,系统会调用默认的拷贝函数——即浅拷贝,它能够完成成员的一一复制。当数据成员中没有指针时,浅拷贝是可行的。但当数据成员中有指针时,如果采用简单的浅拷贝,则两类中的两个指针将指向同一个地址,当对象快结束时,会调用两次free函数,此时teacher2已经是野指针,指向的内存空间已经被释放掉,再次free会报错;另外,一片空间被两个不同的子对象共享了,只要其中的一个子对象改变了其中的值,那另一个对象的值也跟着改变了所以,这时,必须采用深拷贝。

深拷贝与浅拷贝的区别就在于深拷贝会在堆内存中另外申请空间来储存数据,从而也就解决了指针悬挂的问题。

(3)上述代码的改进

解决办法:释放掉被赋值指针变量的旧指向内存,重新对其开辟新内存存放,主要是为了使两个结构体中name指针地址不同,但是指向的内容一致。

 void test006(){
Tea teacher1, teacher2;
teacher1.name = malloc(sizeof(char)* );
memset(teacher1.name, , );
strcpy(teacher1.name, "aaaa");
teacher1.age = ; teacher2.name = malloc(sizeof(char)* );
memset(teacher2.name, , );
strcpy(teacher2.name, "bbbb");
teacher2.age = ; //结构体赋值
//teacher1 = teacher2;
//-----------------------------------------------
if (teacher1.name != NULL){
free(teacher1.name);
teacher1.name = NULL;
}
teacher1.name = malloc(strlen(teacher2.name) + );
strcpy(teacher1.name, teacher2.name);
//-----------------------------------------------
printf("%s, %d\n", teacher1.name, teacher1.age); if (NULL != teacher1.name){
free(teacher1.name);
teacher1.name = NULL;
}
if (NULL != teacher2.name){
free(teacher2.name);
teacher2.name = NULL;
}
}

​建议:

我们在定义类或者结构体,这些结构的时候,最后都重写拷贝函数,避免浅拷贝这类不易发现但后果严重的错误产生

C语言中结构体的深拷贝和浅拷贝的更多相关文章

  1. C语言中结构体赋值问题的讨论

    今天帮师姐调一个程序的BUG,师姐的程序中有个结构体直接赋值的语句,在我印象中结构体好像是不能直接赋值的,正如数组不能直接赋值那样,我怀疑这个地方有问题,但最后证明并不是这个问题.那么就总结一下C语言 ...

  2. C语言中结构体对齐问题

    C语言中结构体对齐问题 收藏 关于C语言中的结构体对齐问题 1,比如: struct{short a1;short a2;short a3;}A;struct{long a1;short a2;}B; ...

  3. C语言中结构体赋值问题的讨论(转载)

    今天帮师姐调一个程序的BUG,师姐的程序中有个结构体直接赋值的语句,在我印象中结构体好像是不能直接赋值的,正如数组不能直接赋值那样,我怀疑这个地方有问题,但最后证明并不是这个问题.那么就总结一下C语言 ...

  4. Go语言中结构体的使用-第2部分OOP

    1 概述 结构体的基本语法请参见:Go语言中结构体的使用-第1部分结构体.结构体除了是一个复合数据之外,还用来做面向对象编程.Go 语言使用结构体和结构体成员来描述真实世界的实体和实体对应的各种属性. ...

  5. 6. Go 语言中结构体的使用

    1. 结构体的定义格式 在go语言中结果的定义格式如下: 123 type structName struct { filedList} 列子如下: 1234 type Person struct { ...

  6. Go语言中结构体的使用-第1部分结构体

    1 概述 结构体是由成员构成的复合类型.Go 语言使用结构体和结构体成员来描述真实世界的实体和实体对应的各种属性.结构体成员,也可称之为成员变量,字段,属性.属性要满足唯一性.结构体的概念在软件工程上 ...

  7. 关于C语言中结构体中的结构体成员导致的字节对齐问题

    关于结构体的字节对齐是什么,就不赘述,再此附上一篇文章,介绍字节对齐:http://www.linuxsong.org/2010/09/c-byte-alignment/ 这里的结构体字节对齐的数据类 ...

  8. C语言中结构体參数变量的传递

    [文章摘要] 在C语言中,结构体參数变量常常作为函数的參数来进行传递.但假设參数设置不当.会出现内存问题. 本文以实际的程序代码为例.具体地介绍怎样正确地使用结构体參数变量.为相关的开发工作提供了參考 ...

  9. C语言中结构体的访问方法解读

    在C语言中,对结构体的访问一般有两种常规方式:"."访问和"->"访问.那么两者有什么区别呢?对C语言有一定了解的同学应该知道,我们新建一个结构体的时候, ...

随机推荐

  1. 【转载】opencl中设备内存

    地址空间限定符 一般的内核代码中,里面的内核参数或声明变量时,都会有地址空间限定符 地址空间限定符,地址空间限定符的主要作用是指出数据应该保存在哪个地方 地址空间限定符有4个: 全局内存: 限定符:_ ...

  2. platform模块和ctypes模块

    一.ctypes模块 Python 的 ctypes 要使用 C 函数,需要先将 C 编译成动态链接库的形式,即 Windows 下的 .dll 文件,或者 Linux 下的 .so 文件.先来看一下 ...

  3. myeclipse CTRL+1功能

    有时候,在myeclipse或者eclipse中自动编译代码有错误,我们把鼠标放在错误一行能够自动显示出问题原因,但是有时显示问题让人有些匪夷所思,不知所云何物. 此时可以使用<ctrl> ...

  4. cookie的设置与销毁

    <?php /* 2个参数设置cookie cookie随着浏览器的关闭,就失效了 ); /* 下面我们让cookir多活一会 3个参数来设置cookie,第3个参数指的就是cookie的声明周 ...

  5. .net core 3.0 发布 500.0 - ANCM In-Process Handler Load Failure 错误

    .net core 3.0 发布后报500.0错误  原因: 发布设置和下载的Runtime SDK不匹配 https://dotnet.microsoft.com/download/dotnet-c ...

  6. IENumerable_Test

    using System; using System.Collections; using System.Collections.Generic; using System.Linq; using S ...

  7. Java基础拾遗(二) — 关于equals(),hashcode()和 ==

    这里分别讲==和equals()的关系,以及equals()和hashcode()的关系 讲解之前,需要先明白对象的内容.对象的引用,基本类型,引用类型这几个概念,此处不做解释 一.==和equals ...

  8. python数据池,python3编码str转bytes,encode

    一.python2 python3的区别 默认编码:2--ASCII码  3---UTF-8 print:python2 可以不需要加括号(),python3必须加括号 python2中有range, ...

  9. Censored! POJ - 1625 AC自动机+大数DP

    题意: 给出一n种字符的字典,有p个禁用的单词, 问能组成多少个不同的长度为m的合法字符串.(m<=50) 题解: 是不是个我们之前做的题目非常非常像,题意都一样. 直接将上次写的AC自动机+矩 ...

  10. 16-3-es5解析顺序

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...