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语言中结构体的深拷贝和浅拷贝的更多相关文章
- C语言中结构体赋值问题的讨论
今天帮师姐调一个程序的BUG,师姐的程序中有个结构体直接赋值的语句,在我印象中结构体好像是不能直接赋值的,正如数组不能直接赋值那样,我怀疑这个地方有问题,但最后证明并不是这个问题.那么就总结一下C语言 ...
- C语言中结构体对齐问题
C语言中结构体对齐问题 收藏 关于C语言中的结构体对齐问题 1,比如: struct{short a1;short a2;short a3;}A;struct{long a1;short a2;}B; ...
- C语言中结构体赋值问题的讨论(转载)
今天帮师姐调一个程序的BUG,师姐的程序中有个结构体直接赋值的语句,在我印象中结构体好像是不能直接赋值的,正如数组不能直接赋值那样,我怀疑这个地方有问题,但最后证明并不是这个问题.那么就总结一下C语言 ...
- Go语言中结构体的使用-第2部分OOP
1 概述 结构体的基本语法请参见:Go语言中结构体的使用-第1部分结构体.结构体除了是一个复合数据之外,还用来做面向对象编程.Go 语言使用结构体和结构体成员来描述真实世界的实体和实体对应的各种属性. ...
- 6. Go 语言中结构体的使用
1. 结构体的定义格式 在go语言中结果的定义格式如下: 123 type structName struct { filedList} 列子如下: 1234 type Person struct { ...
- Go语言中结构体的使用-第1部分结构体
1 概述 结构体是由成员构成的复合类型.Go 语言使用结构体和结构体成员来描述真实世界的实体和实体对应的各种属性.结构体成员,也可称之为成员变量,字段,属性.属性要满足唯一性.结构体的概念在软件工程上 ...
- 关于C语言中结构体中的结构体成员导致的字节对齐问题
关于结构体的字节对齐是什么,就不赘述,再此附上一篇文章,介绍字节对齐:http://www.linuxsong.org/2010/09/c-byte-alignment/ 这里的结构体字节对齐的数据类 ...
- C语言中结构体參数变量的传递
[文章摘要] 在C语言中,结构体參数变量常常作为函数的參数来进行传递.但假设參数设置不当.会出现内存问题. 本文以实际的程序代码为例.具体地介绍怎样正确地使用结构体參数变量.为相关的开发工作提供了參考 ...
- C语言中结构体的访问方法解读
在C语言中,对结构体的访问一般有两种常规方式:"."访问和"->"访问.那么两者有什么区别呢?对C语言有一定了解的同学应该知道,我们新建一个结构体的时候, ...
随机推荐
- hive 总结三(压缩)
本文参考:黑泽君相关博客 本文是我总结日常工作中遇到的坑,结合黑泽君相关博客,选取.补充了部分内容. 开启 map 输出阶段压缩可以减少 job 中 map 和 Reduce task 间数据传输量. ...
- MediatR 知多少 - 简书
原文:MediatR 知多少 - 简书 引言 首先不用查字典了,词典查无此词.猜测是作者笔误将Mediator写成MediatR了.废话少说,转入正题. 先来简单了解下这个开源项目MediatR(作者 ...
- 13-7-return的高级使用
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- READING | 我是一只IT小小鸟
“世界是如此的熙熙攘攘,让年轻的心找不到方向,但这些人是不能小看的啊,如果他们开始敲打自己的命令行.” “知之者不如好知者,好之者不如乐之者”,很多IT界的优秀人才都对计算机技术或者IT技术有着浓厚的 ...
- Oracle批量更改用户下表空间
--查询某个用户下的表,并生成一个修改其命名空间的批处理语句 select 'alter table '|| table_name ||' move tablespace 要迁入的表空间;' from ...
- task code
using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks ...
- 如何在 Apache Flink 中使用 Python API?
本文根据 Apache Flink 系列直播课程整理而成,由 Apache Flink PMC,阿里巴巴高级技术专家 孙金城 分享.重点为大家介绍 Flink Python API 的现状及未来规划, ...
- Joomla - 菜单系统 (从创建到前端页面显示的过程)
在 Joomla 中,菜单是最常用且重要的功能之一,一般用于承载页面内容和各内容间的切换.导航等,演绎着非常重要的角色: 一.新建菜单 进入后台,点击顶栏菜单 -> 菜单管理 -> 点击新 ...
- VMware的下载安装
在学习使用LINNX系统之前,先在自己的电脑上安装一个虚拟机,流行的虚拟机软件有VMware(VMWare ACE).Virtual Box和Virtual PC,它们都能在Windows系统上虚拟出 ...
- CI框架 session 不能读取的问题,PHP7环境
根本原因在这,libraries/Session/Session.php 中 128行: 如果sessionid的长度不是40的话,每次执行都会 unset($_COOKIE[ci_session]) ...