一. 什么是拷贝构造函数
首先对于普通类型的对象来说,它们之间的复制是很简单的,例如:
int a = 100;
int b = a;
而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量。
下面看一个类对象拷贝的简单例子。
#include <iostream>
using namespace std;
class CExample {
private:
int a;
public:
//构造函数
CExample(int b)
{ a = b;}
//一般函数
void Show ()
{
cout<<a<<endl;
}
};
int main()
{
CExample A(100);
CExample B = A; //注意这里的对象初始化要调用拷贝构造函数,而非赋值
B.Show ();
return 0;
}
运行程序,屏幕输出100。从以上代码的运行结果可以看出,系统为对象 B 分配了内存并完成了与对象 A 的复制过程。就类对象而言,相同类型的类对象是通过拷贝构造函数来完成整个复制过程的。
下面举例说明拷贝构造函数的工作过程。
#include <iostream>
using namespace std;
class CExample {
private:
int a;
public:
//构造函数
CExample(int b)
{ a = b;}
//拷贝构造函数
CExample(const CExample& C)
{
a = C.a;
}
//一般函数
void Show ()
{
cout<<a<<endl;
}
};
int main()
{
CExample A(100);
CExample B = A; // CExample B(A); 也是一样的
B.Show ();
return 0;
}
CExample(const CExample& C) 就是我们自定义的拷贝构造函数。可见,拷贝构造函数是一种特殊的构造函数,函数的名称必须和类名称一致,它必须的一个参数是本类型的一个引用变量。
二. 拷贝构造函数的调用时机
在C++中,下面三种对象需要调用拷贝构造函数!(传递对象给函数参数、函数返回对象、对象初始化另一个对象)
1. 对象以值传递的方式传入函数参数
class CExample
{
private:
int a;
public:
//构造函数
CExample(int b)
{
a = b;
cout<<"creat: "<<a<<endl;
}
//拷贝构造
CExample(const CExample& C)
{
a = C.a;
cout<<"copy"<<endl;
}
//析构函数
~CExample()
{
cout<< "delete: "<<a<<endl;
}
void Show ()
{
cout<<a<<endl;
}
};
//全局函数,传入的是对象
void g_Fun(CExample C)
{
cout<<"test"<<endl;
}
int main()
{
CExample test(1);
//传入对象
g_Fun(test);
return 0;
}
调用g_Fun()时,会产生以下几个重要步骤:
(1)test对象传入形参时,会先会产生一个临时变量,就叫 C 吧。
(2)然后调用拷贝构造函数把test的值给C。 整个这两个步骤有点像:CExample C(test);
(3)等g_Fun()执行完后, 析构掉 C 对象。
运行结果:
2. 对象以值传递的方式从函数返回
class CExample
{
private:
int a;
public:
//构造函数
CExample(int b)
{
a = b;
}
//拷贝构造
CExample(const CExample& C)
{
a = C.a;
cout<<"copy"<<endl;
}
void Show ()
{
cout<<a<<endl;
}
};
//全局函数
CExample g_Fun()
{
CExample temp(0);
return temp;
}
int main()
{
g_Fun();
return 0;
}
当g_Fun()函数执行到return时,会产生以下几个重要步骤:
(1)先会产生一个临时变量,就叫XXXX吧。
(2).然后调用拷贝构造函数把temp的值给XXXX。整个这两个步骤有点像:CExample XXXX(temp);
(3)在函数执行到最后先析构temp局部变量。
(4)等g_Fun()执行完后再析构掉XXXX对象。
3. 对象需要通过另外一个对象进行初始化;
CExample A(100);
CExample B = A;
// CExample B(A);
后两句都会调用拷贝构造函数。