0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

C++之拷贝构造函数的浅copy及深copy

电子设计 来源:电子设计 作者:电子设计 2020-12-24 15:31 次阅读

一、深拷贝和浅拷贝构造函数总结:

1、两个特殊的构造函数:

(1)无参构造函数:

没有参数的构造函数

Class Test

public
Test()

//这是一个无参构造函数

};

当类中没有定义构造函数时,编译器默认提供一个无参构造函数,并且其函数体为空;换句话来说,就是我们在类中,不用我们程序猿自己写,编译就自动提供了无参构造函数(只是我们肉眼看不到!)

#include <iostream>
#include <string>
class Test{
//编译器默认给我们提供了一个无参构造函数,只是我们肉眼看不到
};
int main()

Test t;
return 0;

结果输出(编译时能够通过的):

root@txp-virtual-machine:/home/txp# g++ test.cpp
root@txp-virtual-machine:/home/txp#

(2)拷贝构造函数:

参数为const class_name&的构造函数

class Test{
public:
Test(const Test& p)




当类中没有定义拷贝构造函数时,编译器默认提供了一个拷贝构造函数,简单的进行成员变量的值赋值

#include <iostream>
#include <string>
class Test{
private:
int i;
int j;
public:
Test(const Test& p)编译器默认提供这样操作的

i = p.i;
j = p.j;

};
int main()

Test t;
return 0;

输出结果(编译可以通过):

root@txp-virtual-machine:/home/txp# g++ test.cpp
root@txp-virtual-machine:/home/txp#

(3)注意:

在写程序的时候,定义的类对象初始化时看属于哪种类型的:

Test t;//对应无参构造函数
Test t(1);//对应有参构造函数
Test t1;
Test t2=t1;//对应拷贝构造函数

比如下面我定义的类对象属于无参构造函数(当然前提是你手写了其他构造函数,虽然说编译器会默认提供,但是既然要手写,那么三种构造函数就在定义类对象的时候按需求来写),如果只写了有参数构造函数,那么编译器就会报错:

#include <iostream>
#include <string>
class Test{
private:
int i;
int j;
public:
Test(int a)

i = 9;
j=8;

Test(const Test& p)

i = p.i;
j = p.j;

};
int main()

Test t;
return 0;

输出结果:

root@txp-virtual-machine:/home/txp# g++ test.cpp
test.cpp: In function ‘int main()’:
test.cpp:25:9: error: no matching function for call to ‘Test::Test()’
Test t;

test.cpp:25:9: note: candidates are:
test.cpp:15:3: note: Test::Test(const Test&)
Test(const Test& p)

test.cpp:15:3: note: candidate expects 1 argument, 0 provided
test.cpp:10:3: note: Test::Test(int)
Test(int a)

test.cpp:10:3: note: candidate expects 1 argument, 0 provided

4、拷贝构造函数的意义:

(1)浅拷贝

拷贝后对象的物理状态相同

(2)深拷贝

拷贝后对象的逻辑状态相同

(3)编译器提供的拷贝构造函数只进行浅拷贝

代码版本一:

#include <stdio.h>
#include <string>
class Test{
private:
int i;
int j;
int *p;
public:
int getI()

return i;

int getJ()

return j;

int *getP()

return p;

Test(int a)

i = 2;
j = 3;
p = new int;
*p = a;

void free()

delete p;

};
int main()

Test t1(3);//Test t1 3;
Test t2 = t1;
printf("t1.i = %d, t1.j = %d, t1.p = %p", t1.getI(), t1.getJ(), t1.getP());
printf("t2.i = %d, t2.j = %d, t2.p = %p", t2.getI(), t2.getJ(), t2.getP());
t1.free();
t2.free();

return 0;

输出结果:

root@txp-virtual-machine:/home/txp# g++ test.cpp
root@txp-virtual-machine:/home/txp# ./a.out
t1.i = 2, t1.j = 3, t1.p = 0x1528010
t2.i = 2, t2.j = 3, t2.p = 0x1528010
*** Error in `./a.out': double free or corruption (fasttop): 0x0000000001528010 ***
Aborted (core dumped)

注解:出现了段错误,仔细分析,我们发现这里释放了堆空间两次(因为我们这里没有调用拷贝构造函数,也就是自己去写拷贝构造函数;所以这种情况是浅拷贝,不能释放两次堆空间):

代码版本二(加上拷贝构造函数):

#include <stdio.h>
#include <string>
class Test{
private:
int i;
int j;
int *p;
public:
int getI()

return i;

int getJ()

return j;

int *getP()

return p;

Test(int a)

i = 2;
j = 3;
p = new int;
*p = a;

Test(const Test& t)

i = t.i;
j = t.j;
p = new int;
*p = *t.p;

void free()

delete p;

};
int main()

Test t1(4);
Test t2 = t1;
printf("t1.i = %d, t1.j = %d, t1.p = %p", t1.getI(), t1.getJ(), t1.getP());
printf("t2.i = %d, t2.j = %d, t2.p = %p", t2.getI(), t2.getJ(), t2.getP());
t1.free();
t2.free();
return 0;

输出结果:

root@txp-virtual-machine:/home/txp# g++ test.cpp
root@txp-virtual-machine:/home/txp# ./a.out
t1.i = 2, t1.j = 3, t1.p = 0xb0a010
t2.i = 2, t2.j = 3, t2.p = 0xb0a030

注解:从打印的p地址空间来看,就知释放的两个对象的堆空间不同,不再是指向同一堆空间了;同时我们发现浅拷贝只是简单数值上的进行赋值而已;深拷贝不只是简单的值赋值,而是从内存的角度来看,是操作不同的内存。

5、什么时候需要进行深拷贝?

(1)对象中有成员指代了系统中的资源

成员指向了动态内存空间

成员打开了外存中的文件

成员使用了系统中的网络端口

注意:一般来说,自定义拷贝构造函数(也就是我们自己手写的),必然需要实现深拷贝!

二、总结:

C++编译器会默认提供构造函数

无参构造函数用于定义对象的默认初始化状态

拷贝构造函数在创建对象时拷贝对象的状态

对象的拷贝有浅拷贝和深拷贝两种方式。

好了,今天的分享就到这里,如果文章中有错误或者不理解的地方,可以交流互动,一起进步。我是txp,下期见!

审核编辑:符乾江
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 可编程逻辑
    +关注

    关注

    7

    文章

    512

    浏览量

    43907
  • C++
    C++
    +关注

    关注

    21

    文章

    2066

    浏览量

    72903
收藏 人收藏

    评论

    相关推荐

    TC212 Flash copy to RAM区出现异常的原因?

    TC212 刷boot然后刷应用程第一次上电flash copy to RAM 正常.(对应flash区数据变化,但对应的RAM区未变化)第二次刷应用程序,flash copy to RAM(ram区保存第一次刷的数据)每次刷完程序都是从新上电
    发表于 02-19 06:58

    TC397不使能SWAP功能的情况下,对UCB_SWAP_ORIG/_COPY操作会锁芯片吗?

    我想测试一下对UCB_SWAP_ORIG/_COPY的写入/擦除操作,请问在不使能SWAP的情况下,对芯片的这种操作是否会锁片。
    发表于 02-05 08:04

    lsl文件中将text段copy到ram,编译器具体是如何实现的?

    lsl文件中,将text段copy到ram,编译器具体是如何实现的?
    发表于 02-02 07:23

    如何知道UCB COPY扇区的确认状态?

    ”,UCB COPY 扇区仍设置为 “未读”。 SSW 是否只更新 ORIG 扇区的 PROIN 位? 如何知道复制区域处于已确认或已解锁状态? 如果状态为 UNREAD,我应该直接从 0xAF4 的相应的 UCB 扇区位置读取值,还是应该使用其他寄存器?
    发表于 01-22 07:39

    如何进行零拷贝性能测试

    TogetherROS™·Bot零拷贝性能测试 我们使用TogetherROS™·Bot系统内部集成的性能测试工具——performance_test,来评估下开启零拷贝前后的性能差异,这里我们传输
    的头像 发表于 11-27 16:51 195次阅读
    如何进行零<b class='flag-5'>拷贝</b>性能测试

    探索C++的编程习惯与编程要点

    C++的类可以分为带指针数据成员与不带指针数据成员两类,complex就属于不带指针成员的类。而这里要说的字符串类String,一般的实现会带有一个char *指针。带指针数据成员的类,需要自己实现class三大件:拷贝构造
    的头像 发表于 11-14 09:25 220次阅读
    探索<b class='flag-5'>C++</b>的编程习惯与编程要点

    传统IO演化至零拷贝的过程

    拷贝(Zero-Copy)用于在数据读写过程中减少不需要的CPU拷贝,CPU就那么几个,减少它的负担自然可以提高处理效率。数据传输有本地的文件拷贝和通过socket进行文件传输两种,
    的头像 发表于 11-09 09:09 238次阅读
    传统IO演化至零<b class='flag-5'>拷贝</b>的过程

    什么是C++函数? 应该怎么定义? 用途是什么?

    什么是C++函数? 应该怎么定义? 主要用途是什么?
    发表于 11-08 06:58

    静态代码块、构造代码块、构造函数及普通代码块的执行顺序

    在Java中,静态代码块、构造代码块、构造函数、普通代码块的执行顺序是一个笔试的考点,通过这篇文章希望大家能彻底了解它们之间的执行顺序。 1、静态代码块 ①、格式 在java类中(方法中不能存在静态
    的头像 发表于 10-09 15:40 437次阅读
    静态代码块、<b class='flag-5'>构造</b>代码块、<b class='flag-5'>构造</b><b class='flag-5'>函数</b>及普通代码块的执行顺序

    C++生成Dll与回调函数测试

    描述了VS环境下,通过C++生成dll的方法,测试回调函数
    的头像 发表于 08-29 16:05 644次阅读
    <b class='flag-5'>C++</b>生成Dll与回调<b class='flag-5'>函数</b>测试

    iTOP-STM32MP157开发板应用层和内核层传递数据

    的数据字节数 功能 : 将用户空间数据拷贝到内核空间 内核空间-->用户空间,如下图所示: 函数 : copy_to_user(void __user *to, const void
    发表于 08-29 09:54

    C++拷贝和浅拷贝详解

    当类的函数成员存在指针成员时会产生深拷贝和浅拷贝和问题。
    发表于 08-21 15:05 186次阅读
    <b class='flag-5'>C++</b>深<b class='flag-5'>拷贝</b>和浅<b class='flag-5'>拷贝</b>详解

    工业树莓派安全拷贝

    Secure Copy(scp)是一个通过SSH发送文件的命令。这意味着你可以在电脑之间复制文件,比如从树莓派复制到你的桌面或笔记本电脑,反之亦然。
    的头像 发表于 08-07 16:24 351次阅读

    嵌入式-C++函数的重载

    一、什么是函数的重载 两个以上的函数,具有相同的函数名,通过参数的类型和参数的个数不同。编译器自行匹配,自动确定调用哪一个函数 二、函数重载
    发表于 06-28 13:54

    c++常见函数

    c++常见函数集包括:线性代数方程组的解法、插值、数值积分、特殊函数函数逼近、随机数排序、特征值问题、数据拟合、方程求根和非线性方程组的解法、函数
    发表于 05-09 14:52 1次下载