[C++ 从入门到精通] 11.拷贝构造函数

发布时间:2023年12月17日
  • 📢博客主页:https://loewen.blog.csdn.net
  • 📢欢迎点赞 👍 收藏 ?留言 📝 如有错误敬请指正!
  • 📢本文由 丶布布原创,首发于 CSDN,转载注明出处🙉
  • 📢现在的付出,都会是一种沉淀,只为让你成为更好的人?


一. 定义

拷贝构造函数:如果一个类构造区数的第一个参数是所属的类类型的引用。如果后面还有其他额外参数,并且后面这些额外的参数还都有默认值,则这个构造函数就叫拷贝构造函数。

注意:拷贝构造函数默认参数必须放在函数声明中,除非该函数没有函数声明。

建议:

  1. 拷贝构造函数第一个参数总是带着const,作用参考前面的文章:传送门
  2. explicit:拷贝构造函数一般不要声明成explicit(禁止隐式转换),作用参考前面的文章:传送门
class Time
{
public:
	Time();
	int Hour;
	int Minute;
	int Second;
	
	//拷贝构造函数(在类对象赋值的时候,给对象一些值),
	Time(const Time &tmptime,int a = 5);
};

Time::Time():Hour(11), Minute(58), Second(49)
{
	std::cout << "调用了Time::Time()构造区数" << std::endl;
}

Time::Time(const Time &tmptime, int a):Hour(12),Minute(59), Second(50)
{
	std::cout << "调用了Time::Time(Time &taptime, int a)拷贝构造区数" << std::endl;
}

二. 调用场景

作用会在一定的时机(定义类对象的同时被赋值),被系统默认调用。

如:

int main()
{
	Time myTime;               //调用默认构造函数(不带参数)
	Time myTime2 = myTime;     //调用拷贝构造函数
	Time myTime3(myTime);      //调用拷贝构造函数
	Time myTime4{ myTime };    //调用拷贝构造函数
	Time myTime5 = { myTime }; //调用拷贝构造函数
	Time myTime6;              //调用默认构造函数(不带参数)
	myTime6 = myTime5;         //从运行结果来看,没有调用拷贝构造函数,后面在拓展,这里暂不考虑

    system("pause");
	return 0;
}

在这里插入图片描述

此外,还有其他调用拷贝构造函数的情景:

1、将一个对象作为实参传递给一个非引用类型的形参。

void func(Time tmptime)
{
	std::cout << "调用了Time::Time(Time &taptime, int a)拷贝构造区数" << std::endl;
}
int main()
{
	Time myTime;
	func(myTime);	
}

运行结果:

在这里插入图片描述

2、从一个函数中返回一个对象的时候。

Time func()
{
	Time tmpTime;
	return tmpTime;  //系统产生了临时对象并且调用了类的拷贝构造函数
}
int main()
{
	func();	 //等价于 Time myTime = func();
}

运行结果:

在这里插入图片描述

3、还有一些其他调用拷贝构造函数的情况以后补充。


三. 其他特性

我们前面说过,默认情况下,类对象的拷贝是每个成员变量的逐个拷贝。

成员变量逐个拷贝的功能因为定义的拷贝构造函数的存在而丢失了作用,或者说我们自己定义的拷贝构造函数取代了系统默认的每个成员变量逐个拷贝的这种行为。

a) 如果我们没有为类定义拷贝构造函数,编译器就会帮我们定义一个“合成拷贝构造函数”。

b) 编译器帮我们定义的“合成拷贝构造函数”一般也是将类对象tmptime的成员逐个拷贝到正在创建的对象中(Time myTime2 = myTime)。
每个成员的类型决定它如何拷贝:

  • 若是整型的,那么就直接把值拷贝过来赋值给正在创建的类对象;
  • 若是类类型的,那么就调用类类型的这个类的拷贝构造函数来拷贝赋值给正在创建的类对象(若自己定义了类A的拷贝构造函数,则不会调用在类A声明的类B的拷贝构造函数,只调用类B构造函数);

c) 如果自己定义了拷贝构造函数,那么系统就不会在定义“合成拷贝构造函数”,这时必须在自己定义的拷贝构造函数给类成员赋值,以免出现类成员没有被赋值就使用的情况发生。

假设我们在类成员函数中,对成员变量进行赋初值,而在拷贝构造函数中,不对成员变量进行赋初值。

Time::Time():Hour(11), Minute(58), Second(49)
{
	std::cout << "调用了Time::Time()构造区数" << std::endl;
}

Time::Time(const Time &tmptime, int a)
{
	std::cout << "调用了Time::Time(Time &taptime, int a)拷贝构造区数" << std::endl;
}

运行结果如下:所以必须在自己定义的拷贝构造函数给类成员赋值

```
![在这里插入图片描述](https://img-blog.csdnimg.cn/0a8d5202fa874c60835a94d4be3fd6d4.png)


态度"ABC"理论的三个维度,即情感(Affective)、行为(Behavioral)和认知(Cognitive)
文章来源:https://blog.csdn.net/weixin_43197380/article/details/134377657
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。