C++从入门到精通——类的6个默认成员函数之拷贝构造函数

慈云数据 6个月前 (05-13) 技术支持 85 0

拷贝构造函数

  • 前言
  • 一、拷贝构造函数概念
    • 理解
    • 定义
    • 二、拷贝构造函数的特征
    • 三、注意要点
      • 写法
      • 实践
      • 传址返回与引用返回的区别
        • 传址返回
        • 引用返回
        • 传值返回和传址返回的对比
        • 总结
        • 测试

          前言

          类的6个默认成员函数:如果一个类中什么成员都没有,简称为空类。

          空类中真的什么都没有吗?并不是,任何类在什么都不写时,编译器会自动生成以下6个默认成员函数。

          默认成员函数:用户没有显式实现,编译器会生成的成员函数称为默认成员函数。

          class Date {};
          

          在这里插入图片描述


          一、拷贝构造函数概念

          理解

          在现实生活中,可能存在一个与你一样的自己,我们称其为双胞胎。

          在这里插入图片描述

          那在创建对象时,可否创建一个与已存在对象一某一样的新对象呢?

          定义

          拷贝构造函数:只有单个形参,该形参是对本类类型对象的引用(一般常用const修饰),在用已存在的类类型对象创建新对象时由编译器自动调用。

          C++拷贝构造函数是一种特殊的构造函数,用于创建对象时,使用一个已有对象的内容来初始化新的对象。它接受一个同类对象作为参数,并按照该对象的数据成员的值来创建新的对象。

          拷贝构造函数通常用于以下情况:

          • 在创建对象时,使用同类已有对象的值来初始化新对象。
          • 以值传递方式将对象传递给函数。
          • 以值返回方式从函数返回对象。

            拷贝构造函数的定义形式为:

            类名(const 类名&obj)
            {
                // 构造函数的实现
            }
            

            其中,类名是要创建的对象的类名,obj是要拷贝的对象。

            拷贝构造函数的工作原理是将obj的数据成员的值复制给新创建的对象。这意味着新对象的数据成员会与原对象具有相同的值,但是它们是独立的,改变其中一个对象的数据成员的值不会影响另一个对象的数据成员。

            如果没有显式定义拷贝构造函数,编译器会提供一个默认的拷贝构造函数。默认的拷贝构造函数执行的是浅拷贝,即简单地将原对象的值复制给新对象的数据成员。如果类中包含指针类型的数据成员,需要自己定义拷贝构造函数,进行深拷贝,确保指针指向的对象也被复制。

            注意,拷贝构造函数是类成员函数,通常定义在类的公有部分。拷贝构造函数是通过对象名来调用的,而不是通过函数名来调用。

            二、拷贝构造函数的特征

            拷贝构造函数也是特殊的成员函数,其特征如下:

            1. 拷贝构造函数是构造函数的一个重载形式。
            2. 拷贝构造函数的参数只有一个且必须是类类型对象的引用,使用传值方式编译器直接报错,因为会引发无穷递归调用。
            class Date
            {
            public:
            	Date(int year = 1900, int month = 1, int day = 1)
            	{
            		_year = year;
            		_month = month;
            		_day = day;
            	}
            	// Date(const Date& d)   // 正确写法
            	Date(const Date d)   // 错误写法:编译报错,会引发无穷递归
            	{
            		_year = d._year;
            		_month = d._month;
            		_day = d._day;
            	}
            private:
            	int _year;
            	int _month;
            	int _day;
            };
            int main()
            {
            	Date d1;
            	Date d2(d1);
            	return 0;
            }
            

            在这里插入图片描述

            3. 若未显式定义,编译器会生成默认的拷贝构造函数。 默认的拷贝构造函数对象按内存存储按字节序完成拷贝,这种拷贝叫做浅拷贝,或者值拷贝。

            和构造函数不一样,构造函数内置类型不会初始化,拷贝构造函数会初始化

            class Time
            {
            public:
            	Time()
            	{
            		_hour = 1;
            		_minute = 1;
            		_second = 1;
            	}
            	Time(const Time& t)
            	{
            		_hour = t._hour;
            		_minute = t._minute;
            		_second = t._second;
            		cout 
            private:
            	// 基本类型(内置类型)
            	int _year = 1970;
            	int _month = 1;
            	int _day = 1;
            	// 自定义类型
            	Time _t;
            };
            int main()
            {
            	Date d1;
            	// 用已经存在的d1拷贝构造d2,此处会调用Date类的拷贝构造函数
            	// 但Date类并没有显式定义拷贝构造函数,则编译器会给Date类生成一个默认的拷贝构造函数
            	Date d2(d1);
            	return 0;
            }
            
            public:
            	Stack(size_t capacity = 10)
            	{
            		_array = (DataType*)malloc(capacity * sizeof(DataType));
            		if (nullptr == _array)
            		{
            			perror("malloc申请空间失败");
            			return;
            		}
            		_size = 0;
            		_capacity = capacity;
            	}
            	void Push(const DataType& data)
            	{
            		// CheckCapacity();
            		_array[_size] = data;
            		_size++;
            	}
            	~Stack()
            	{
            		if (_array)
            		{
            			free(_array);
            			_array = nullptr;
            			_capacity = 0;
            			_size = 0;
            		}
            	}
            private:
            	DataType* _array;
            	size_t _size;
            	size_t _capacity;
            };
            int main()
            {
            	Stack s1;
            	s1.Push(1);
            	s1.Push(2);
            	s1.Push(3);
            	s1.Push(4);
            	Stack s2(s1);
            	return 0;
            }
            
            public:
            	Date(int year, int minute, int day)
            	{
            		cout 
            		cout 
            		cout 
            	Date temp(d);
            	return temp;
            }
            int main()
            {
            	Date d1(2022, 1, 13);
            	Test(d1);
            	return 0;
            }
            
            public:
            	Date(int year = 1900, int month = 1, int day = 1)
            	{
            		_year = year;
            		_month = month;
            		_day = day;
            	}
            	// Date(const Date& d)   // 正确写法
            	Date(const Date& d)   // 错误写法:编译报错,会引发无穷递归
            	{
            		_year = d._year;
            		_month = d._month;
            		_day = d._day;
            	}
            private:
            	int _year;
            	int _month;
            	int _day;
            };
            int main()
            {
            	Date d1;
            	Date d2(d1);
            	return 0;
            }
            
            		cout 
            public:
            	Date(int year = 1900, int month = 1, int day = 1)
            	{
            		cout
            		cout 
            		cout 
            	Date temp(d);
            	return temp;
            }
            //Date& fun()
            //{
            //	Date d(2024,4,14);
            //	return d;
            //}
            int main()
            {
            	Date d;
            	func(d);
            	//const Date& ret = func();
            	return 0;
            }
            //class Date
            //{
            //public:
            //	Date(int year, int minute, int day)
            //	{
            //		cout 
            //		cout 
            //		cout 
            //	Date temp(d);
            //	return temp;
            //}
            //int main()
            //{
            //	Date d1(2022, 1, 13);
            //	Test(d1);
            //	return 0;
            //}
            
微信扫一扫加客服

微信扫一扫加客服

点击启动AI问答
Draggable Icon