C++ 拷贝构造函数

定义:

如果一个类的构造函数的第一个参数是所属类类型的引用,而其他参数都有默认值,这个构造函数就是拷贝构造函数。

函数的默认参数必须放在函数声明中,除非该函数没有函数声明。

Time.h

#ifndef _TIME_H
#define _TIME_H
#include<iostream>
using namespace std;

class Timeclass
{
public:
	Timeclass() 
	{
		cout << "调用了Timeclass默认构造函数" << endl;
	}
	Timeclass(Timeclass & Timeclass)
	{
		cout << "调用了Timeclass拷贝构造函数" << endl;
	}

};

class Time
{
public:
	int Hour;
	int min;
	int secend;
private:
	int haomiao;

public:
	//拷贝构造函数,第一个参数为所属类类型的引用,后面的参数都有默认值
	//建议:
	//第一个参数带const
	//一般不要声明称explicit
	Time(const Time& time, int a = 20);
	//构造函数
	explicit Time(int temphour, int tempmin, int tempsecend);
	Time(int temphour, int tempmin);
	explicit Time(int temphour);
	Time();
	//Timeclass cl;

};


#endif


#include"Time.h"
#include<iostream>
//拷贝构造函数,系统自动调用
using namespace std;
Time::Time(const Time& temptime, int a )
{
	cout << "调用了拷贝构造函数" << endl;
}
//explicit 函数显示声明,加上他之后,函数就不会进行隐式转换,
//一般用于一个参数的构造函数,防止把一个数据隐式转换为对象
Time::Time(int temphour, int tempmin, int tempsecend)
	:Hour(temphour), min(tempmin), secend(tempsecend)//参数列表,用于给成员变量初始化,这样做在分配内存时就赋值,效率更高
{
	cout << "调用了Time(int temphour, int tempmin, int tempsecend)构造函数" << endl;
}
Time::Time(int temphour, int tempmin)
{

}
Time::Time(int temphour)
{
	cout << "调用了Time(int temphour)构造函数" << endl;
}
Time::Time()
{
	cout << "调用了默认构造函数" << endl;
}
// C++project.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include"Time.h"

using namespace std;
int main()
{
    //默认情况下,成员变量是逐个拷贝的
    Time mytime1(10, 15, 20);//这个调用默认构造函数(带3个参数)
    Time mytime2 = mytime1;//这个调用拷贝构造函数
    Time mytime3(mytime1);//这个调用拷贝构造函数
    Time mytime4{ mytime1 };//这个调用拷贝构造函数
    Time mytime5 = { mytime1 };//这个调用拷贝构造函数
    Time mytime6(10);//这个调用默认构造函数(无参数)
    mytime6 = mytime5;

    cout << mytime1.Hour <<"\n" << endl; 
    cout << mytime1.min << "\n" << endl;
    cout << mytime1.secend << "\n" << endl;
     
}

 

当进行类的拷贝时,如果没有定义拷贝构造函数,那么系统就会为我们定义一个“合成拷贝构造函数”,将成员变量进行逐个拷贝,如果成员变量是整形、浮点型这类数据,就直接进行值拷贝。果果成员变量包含类类型,就会调用该类的拷贝构造函数进行拷贝。如果自己定义了拷贝构造函数,则系统不会定义。

例如下面这段代码,Time这个类里面没有定义拷贝构造函数,系统就会定义一个合成的拷贝构造函数完成拷贝,Time类中有一个Timeclass类类型的成员变量,在拷贝这个成员变量时,就会掉用这个类的拷贝构造函数。

如果Time这个类里面定义了拷贝构造函数,Time类中有一个Timeclass类类型的成员变量,在拷贝这个成员变量时,不会掉用这个类的拷贝构造函数。

//Time.h文件
#ifndef _TIME_H
#define _TIME_H
#include<iostream>
using namespace std;

class Timeclass
{
public:
	Timeclass() 
	{
		cout << "调用了Timeclass默认构造函数" << endl;
	}
	Timeclass(Timeclass & Timeclass)
	{
		cout << "调用了Timeclass拷贝构造函数" << endl;
	}

};

class Time
{
public:
	int Hour;
	int min;
	int secend;
private:
	int haomiao;

public:
	Time(const Time& time, int a = 20);
	//构造函数
	explicit Time(int temphour, int tempmin, int tempsecend);
	
    Timeclass cl;//类对象

};


#endif


//Time.cpp文件

#include"Time.h"
#include<iostream>
//拷贝构造函数,系统自动调用
using namespace std;

Time::Time(int temphour, int tempmin, int tempsecend)
	:Hour(temphour), min(tempmin), secend(tempsecend)//参数列表,用于给成员变量初始化,这样做在分配内存时就赋值,效率更高
{
	cout << "调用了Time(int temphour, int tempmin, int tempsecend)构造函数" << endl;
}

//主函数

#include <iostream>
#include"Time.h"
using namespace std;
int main()
{
    //默认情况下,成员变量是逐个拷贝的
    Time mytime1(10, 15, 20);//这个调用默认构造函数(带3个参数)
    Time mytime2 = mytime1;//这个调用系统合成拷贝构造函数

}

 还有一些情况,也会调用拷贝构造函数:

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

例如:

void func(Time mytime)
{
    return;
}

func(mytime);//这里就会调用拷贝构造函数

2、从一个函数中返回一个对象时,系统也会调用拷贝构造函数

这里系统会构造一个临时对象,将返回的对象的值拷贝给临时对象返回。

### C++ 拷贝构造函数的概念及用法 #### 什么是拷贝构造函数拷贝构造函数是一种特殊的构造函数,在创建新对象时用于初始化该对象。它接受一个相同类型的已存在对象作为参数,并利用这个已有对象的数据成员来初始化新的对象[^2]。 #### 拷贝构造函数的语法形式 以下是拷贝构造函数的标准声明方式: ```cpp ClassName(const ClassName& other); ``` 这里 `other` 是现有对象的一个常量引用,表示不会修改传入的对象数据。 #### 自动调用的情况 在以下几种情况下会自动调用拷贝构造函数: 1. 当以值传递的方式将对象传递给函数时。 2. 函数返回按值返回对象时。 3. 创建一个新的对象并将其显式初始化为现有的对象实例时[^4]。 例如: ```cpp Student mya("zhang3", 22); // 正常构造函数被调用 Student myb(mya); // 调用了拷贝构造函数 // 或者等价于:Student myb = mya; ``` #### 默认实现的行为 如果没有手动定义拷贝构造函数,则编译器会自动生成默认版本。此默认版本执行的是浅拷贝操作,即简单地逐位复制源对象中的所有字段到目标对象中[^3]。 然而对于某些复杂场景下的类(比如含有动态分配内存或其他资源管理职责),仅依赖这种简单的深拷贝可能会引发问题,因此需要定制化实现深层拷贝逻辑。 #### 定制化的例子 假设我们有一个包含指针成员变量的类: ```cpp class MyClass { public: int* ptr; // 构造函数 explicit MyClass(int value) : ptr(new int(value)) {} // 拷贝构造函数 (Deep Copy) MyClass(const MyClass &source) : ptr(new int(*(source.ptr))) {} ~MyClass() { delete ptr; } }; int main(){ MyClass obj1(10); MyClass obj2(obj1); // 这里触发了我们的拷贝构造函数 cout << *obj1.ptr << endl; // 输出应该是 10 cout << *obj2.ptr << endl; // 同样也是独立副本后的 10 return 0; } ``` 上述代码片段展示了如何正确处理涉及堆上分配空间的情形下所需的深层次复制过程。 #### 总结注意事项 - 如果你的类只包含了基本类型或标准容器之类的安全可复制组件,通常无需额外关注拷贝语义; - 对那些持有裸指针或者其他特殊所有权概念的属性则必须小心对待其生命周期管理问题,可能还需要同步提供合适的析构函数以及赋值运算符重载方法[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值