• 【C++】构造函数和析构函数第二部分(拷贝构造函数)--- 2023.9.28


    什么是拷贝构造函数

    用一句话来描述为拷贝构造即 “用一个已知的对象去初始化另一个对象

    具体怎么使用我们直接看代码,代码如下:

    class Maker
    {
    public:
    	Maker()
    	{
    		cout << "无参构造函数" << endl;
    		a = 20;
    	}
    	
    	Maker(const Maker &m)
    	{
    		cout << "拷贝构造函数" << endl;
    		a = m.a;
    	}
    	//打印函数
    	void printMaker()
    	{
    		cout << "a=" << a << endl;
    	}
    private:
    	int a;
    };
    
    void test01()
    {
    	Maker m1;
    	m1.printMaker();
    	
    	Maker m2(m1);
    	m2.printMaker();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    好!按照老样子,接下来开始详细讲解每行代码的用处,以及为什么这样写!

    Maker m1;
    
    • 1

    //首先实例化一个对象,并且该对象名为m1。

    m1.printMaker();
    
    • 1

    //通过对象m1来调用Maker类中的printMaker()方法。

    Maker m2(m1);
    
    • 1

    //相当于是用一个已有的对象(m1)来初始化另一个对象,并且该对象名为m2,相当于“套娃”,一层套一层。

    m2.printMaker();
    
    • 1

    //使用已经实例化成功的对象m2来调用Maker类中的printMaker()方法。

    Maker(const Maker &m)
    	{
    		cout << "拷贝构造函数" << endl;
    		a = m.a;
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5

    //这里需要大家特别注意,我们使用拷贝构造函数的形参必须要引用,至于为什么,我们一起来探索为什么不能用引用。
    //先上代码:

    class Maker3
    {
    public:
    	Maker3(int Ma)
    	{
    		cout << "有参构造函数" << endl;
    		ma = Ma;
    	}
    	Maker3(const Maker3 m)//注意这里的形参不是引用
    	{
    		cout << "拷贝构造函数" << endl;
    	}
    private:
    	int ma;
    };
    
    void test03()
    {
    	Maker3 m1(10);//调用有参构造
    	Maker3 m2(m1);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    好!按照老样子,接下来开始详细讲解每行代码的用处,以及为什么这样写!

    1. 首先 Maker3 m2(m1);使用了拷贝构造函数,m1为形参。
    2. Maker3 m2(m1); 《===》const Maker3 m=m1;
    3. const Maker3 m=m1; 《===》const Maker3 m(m1);
    4. const Maker3 m(m1); 《===》const Maker3 m=m1;
    5. 然后进入了死循环,接下来会执行const Maker3 m=m1; 《===》const Maker3 m(m1);以此类推。
    6. 所以我们使用拷贝构造函数的条件下,形参应该是引用!!!

    编译器默认的拷贝构造函数

    如果我们使用拷贝构造函数来用一个对象来初始化另一个对象时,忘记在类中创建拷贝构造函数方法,那么此时其实也不会报错,也能正常运行,因为编译器已经默认提供了拷贝构造函数。为了更清楚的展示,先上代码:

    class Maker2
    {
    public:
    	Maker2()
    	{
    		cout << "无参构造函数" << endl;
    		a = 20;
    	}
    	//打印函数
    	void printMaker()
    	{
    		cout << "a=" << a << endl;
    	}
    private:
    	int a;
    };
    
    
    void test02()
    {
    	Maker2 m1;
    	m1.printMaker();
    	
    	Maker2 m2(m1);
    	m2.printMaker();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    //在上述代码中我们并没有在类中创建拷贝构造函数,运行结果如下:在这里插入图片描述

    如上图所示,当对象m2调用printMaker()方法时,并没有报错,而是正常将a的值打印出来,并且打印值没有问题,这是因为编译器已经设置默认的构造函数,那这个构造函数长什么样子呢?如下所示:

    Maker2(const Maker2 &m)
    {
    	a = m.a;
    }
    
    • 1
    • 2
    • 3
    • 4

    //默认拷贝构造函数进行了成员变量的简单拷贝,所以我们才能准确无误的将变量打印出来,即a=m1.a=20。

    构造函数的分类及调用

    构造函数的分类分为三种,分别是:

    1. 无参构造函数
    2. 有参构造函数
    3. 拷贝构造函数

    上述三种均已讲完。

    那么在类中编译器默认提供了哪些函数呢?分别是:

    1. 默认的构造函数
    2. 默认的析构函数
    3. 默认的拷贝构造函数

    我们最后在分析一下这几种构造函数的软件使用方法:

    void test01()
    {
    	Maker m;//调用无参构造函数
    	Maker m1(10);//调用有参构造
    	Maker m2(m1);//调用拷贝构造
    
    	//不常用
    	Maker m4 = Maker(10);//调用的是有参构造函数
    	Maker m3 = m2;//调用拷贝构造
    	Maker m5 = 10;//Maker m5=Maker(10); 调用的是有参构造函数
    
    	Maker m6;
    	m6 = m5;//赋值操作
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    结束语

    如果觉得这篇文章还不错的话,记得点赞 ,支持下!!!

  • 相关阅读:
    2609. 最长平衡子字符串 --力扣 --JAVA
    Postman —— postman的介绍和安装
    Python【理解标识符的定义】
    k8s实战系列:3-存储的花样玩法(下)
    SolVES4.1学习2——导入数据运行模型
    虚拟机(三)VMware Workstation 桥接模式下无法上网
    文档管理控件Aspose.total for.NET 迎来重大更新,全新版本v22.7全新版本来袭,快来看看都有哪些~
    Java的虚拟线程和结构化并发,含完整示例代码
    从零开始Blazor Server(15)--总结
    【CVPR2022】Detecting Camouflaged Object in Frequency Domain
  • 原文地址:https://blog.csdn.net/qq_40544107/article/details/133276796