啃书《C++ Primer Plus》 面向对象部分 深拷贝与浅拷贝问题 拷贝构造函数 赋值函数

本文详细探讨了C++中拷贝构造函数和赋值函数的概念,解释了默认拷贝构造函数和赋值函数的行为,特别是关于深拷贝和浅拷贝的区别。通过实例展示了如何自定义拷贝构造函数和赋值函数以满足特定需求,防止自赋值行为,并解决了引用类型成员带来的问题。此外,文章强调了禁止对象拷贝的情况及其影响。
摘要由CSDN通过智能技术生成

干货长文预警


这一篇,我们来解决对象的赋值与拷贝问题。赋值与拷贝,是程序设计过程中不可或缺的部分,对于基础类型,这两个概念相信大家早已熟知,这里不多赘述。
但是对于自定义类型的对象,拷贝与赋值就有这不同的含义:

拷贝发生在一个对象诞生的时候,基于另一个同类对象进行构造
而赋值则是将一个已存在的对象的内容传递给另一个已存在的对象。

虽然编译器提供了默认的拷贝与赋值函数,又由于对象的数据成员在被赋值或是拷贝时会有着诸如指针指向新内存这些默认函数不能实现的不同行为需求,因此赋值与拷贝操作有时需要重新定义其行为,以满足程序的具体要求。这也就引出了本篇的第二个关键问题:深拷贝与浅拷贝

本文思维导图:
在这里插入图片描述


拷贝构造函数

根据名称,不难知道拷贝构造函数是一种特殊的构造函数,它的任务就是用来拷贝对象。

默认拷贝构造函数

拷贝构造函数享有编译器赋予默认添加的vip特权。当程序中没有拷贝构造函数时,编译器会自动提供一个缺省的拷贝构造函数。这个拷贝构造函数的访问级别是公有的。

在进行拷贝时,默认的拷贝构造函数的行为是固定的,它有两种行为:

  • 普通成员(内置类型,指针等)按位拷贝。
  • 对象成员 执行其拷贝构造函数

对于普通成员,程序将按位进行复制进行拷贝,执行“浅复制”
对于对象成员,程序将调用它的拷贝构造函数进行复制,这个成员的复制的具体行为由其拷贝构造函数决定

对于对象成员拷贝的解读,来看个粟子:

class A{
   
public:
    A(){
   }
    A(const A& a){
   cout << "A类拷贝构造函数" << endl << endl;}
};
class B
{
   
public:
    B(){
   }
    A a;	//对象成员,在默认拷贝构造函数中将被调用其拷贝构造函数
};
int main()
{
   
    B b;
    B c = b; //产生拷贝情况
}

运行结果:
在这里插入图片描述
表示在拷贝B类型对象过程中调用到了A类型拷贝构造函数

另外,我们还漏掉了一类情况:引用类型!!
将上述代码稍作修改,用来观察引用类型成员在默认拷贝构造函数中的行为:

class A{
   
public:
    A(){
   }
    A(const A& a){
   cout << "A类拷贝构造函数" << endl << endl;}
};
class B
{
   
public:
    B():aa(*new A()){
   }	//引用类型必须进行初始化!!!
    A a;	//对象成员,在默认拷贝构造函数中将被调用其拷贝构造函数
    A& aa;
};
int main()
{
   
    B b;
    B c = b; //产生拷贝情况
    cout << "对象成员 " << &b.a << " " << &c.a << endl;
    cout << "引用成员 " << &b.aa << " " << &c.aa << endl;
}

在主函数中打印两个对象的成员地址,用以区分其是否为同一对象。同时,该代码保留了上一份代码对A类拷贝构造函数的提示功能。其运行结果如下:
在这里插入图片描述
不难发现的是,对于引用型的成员,初始化拷贝时直接引用了被拷贝对象的引用,并没有创建新的引用。
考虑到引用在底层是使用指针实现的,相当于一个 A * const类型指针,所以引用成员的拷贝行为就也可以看作是按位复制的结果,仍然是一种“浅拷贝”。

自定义拷贝构造函数

当默认的拷贝构造函数不能满足程序设计需求时,就需要程序员自己来实现拷贝构造函数了。
实现自定义的拷贝构造函数的第一步,就理解拷贝构造函数的书写形式。

拷贝构造函数的形式

重点放在前面
拷贝构造函数声明形式如下:

类名(cosnt 类名& );

实现形式如下:

类名 (const 类名& 引用对象名):初始化列表{构造函数方法体}

作为一种特殊

func3是一个通过对积分进行嵌套积分得到的函数。在给定的代码中,首先定义了一个名为func2的函数,这个函数是对func1在0到x之间进行积分得到的结果。然后,又定义了一个名为func3的函数,这个函数是对func2在0到x之间进行积分得到的结果。最后,使用fplot函数将func1、func2和func3在区间[-10, 10]上绘制出来。根据代码中的注释,绘制的图形应该是保持坐标轴比例一致的。如果你想查看完整的代码并在MATLAB R2019a上运行,可以访问https://mianbaoduo.com/o/bread/YZyVlp9v。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [matlab匿名函数实现含参变量的对分段函数的不定积分及绘图](https://blog.csdn.net/weixin_43699700/article/details/105212739)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [【啃书】《智能优化算法及其MATLAB实例》例7.3模拟退火算法求解TSP问题](https://blog.csdn.net/weixin_44331401/article/details/109175759)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值