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. 软件设计师_朴素模式匹配算法和KMP算法

    1.从主字符串中匹配模式字符串(暴力匹配) 2. KMP算法

  2. JMeter 返回Json数据提取方法

    JMeter中,对response返回JSON格式的数据进行处理,格式如下: { "code":2000, "message":"success&qu ...

  3. CreateRemoteThread简单应用

    要实现线程的远程注入必须使用Windows提供的CreateRemoteThread函数来创建一个远程线程 该函数的原型如下: HANDLE CreateRemoteThread(      HAND ...

  4. Mybatis笔记 – 入门程序开发

    一.Mybatis开发环境 JDK:jdk_1.7 Eclipse:Oxygen.1 Release (4.7.1) MySQL:MySQL Servr 5.7 1.添加相关ja r包 mybatis ...

  5. QT之QSettings 学习

    1.读写配置文件. 代码如下: //创建配置文件 QSettings iniFile(QCoreApplication::applicationDirPath()+"/test.ini&qu ...

  6. java web项目部署到云服务器

    第一步把java web项目打包 成war包 第二步:在Build选里选择build Artfacts->water:war->Build war包建立完毕. 第三步:在官网下载winsc ...

  7. Java学习之Java历史版本

    Java有三个版本,标准版Java SE,企业版Java EE,移动版Java ME.按理来说,每一种版本都会有自己的版本号,但是约定俗成:JDK版本号=Java SE版本号=Java版本号,这是因为 ...

  8. Cefsharp实现快捷键功能

    原文:Cefsharp实现快捷键功能 1 . 实现IKeyboardHandler接口 public class KeyBoardHander : IKeyboardHandler { public ...

  9. Luogu P3033 [USACO11NOV]牛的障碍Cow Steeplechase(二分图匹配)

    P3033 [USACO11NOV]牛的障碍Cow Steeplechase 题意 题目描述 --+------- -----+----- ---+--- | | | | --+-----+--+- ...

  10. Android开发 输入法调用学习

    方法一(如果输入法在窗口上已经显示,则隐藏,反之则显示) InputMethodManager imm = (InputMethodManager) getSystemService(Context. ...