拷贝构造函数 是一种构造函数,用于创建已存在的类对象的副本,它通常采用 X (X&) 的形式,其中 X 是类名,编译器为所有类提供了一个默认的拷贝构造函数。
Classname(const classname & objectname)
{
. . . .
}
由于它用于创建对象,因此称为构造函数,并且,它还创建了一个新对象,是原对象的拷贝,因此称为拷贝构造函数。
以下是 Copy Constructor 的示例程序:
#include<iostream>
using namespace std;
class Samplecopyconstructor
{
private:
int x, y; //成员数据
public:
Samplecopyconstructor(int x1, int y1)
{
x = x1;
y = y1;
}
/* 拷贝构造函数 */
Samplecopyconstructor (const Samplecopyconstructor &sam)
{
x = sam.x;
y = sam.y;
}
void display()
{
cout<<x<<" "<<y<<endl;
}
};
/* 主函数 */
int main()
{
Samplecopyconstructor obj1(10, 15); // 一般的构造函数
Samplecopyconstructor obj2 = obj1; // 拷贝构造函数
cout<<"一般的构造函数: ";
obj1.display();
cout<<"拷贝构造函数: ";
obj2.display();
return 0;
}
以上实例输出结果:
一般的构造函数: 10 15 拷贝构造函数: 10 15
通过一个例子来解释浅拷贝构造函数的概念:两名学生正在通过网络共享的两台不同机器,他们同时在 Excel 表中输入他们的详细信息,他们俩所做的更改将反映在excel表中,因为在两个位置都打开了相同的 Excel 表,这就是浅拷贝构造函数中发生的情况,两个对象都将指向相同的内存位置。
浅拷贝只是对原始对象的引用,默认拷贝构造函数提供一个浅拷贝,如下例所示,它是对象的按位复制,当类使用默认拷贝构造函数时,类使用的是浅拷贝,它不会动态分配内存。
在下面的示例中,你可以看到两个对象 c1 和 c2 都指向相同的内存位置,当 c1.concatenate()
函数被调用时,它也会影响 c2,所以 c1.display()
和 c2.display()
都会给出相同的输出。
#include<iostream>
#include<cstring>
using namespace std;
class CopyConstructor
{
char *s_copy;
public:
CopyConstructor(const char *str)
{
s_copy = new char[16]; // 动态分配内存
strcpy(s_copy, str);
}
/* 连接字符串 */
void concatenate(const char *str)
{
strcat(s_copy, str); //连接两个字符串
}
/* 析构函数 */
~CopyConstructor ()
{
delete [] s_copy;
}
void display()
{
cout<<s_copy<<endl;
}
};
int main()
{
CopyConstructor c1("Copy");
CopyConstructor c2 = c1; // 浅拷贝
c1.display();
c2.display();
c1.concatenate("Constructor"); //c1调用concatenate()
c1.display();
c2.display();
return 0;
}
以上实例输出结果:
Copy Copy CopyConstructor CopyConstructor
让我们再来看一个深拷贝构造函数的例子:假如你明天要提交作业,时间不够,所以你从朋友那里抄了它,现在你和你的朋友拥有相同的作业内容,但不同的副本,因此,在你的作业副本中所做的任何修改都不会反映在你朋友的副本中,这就是在深拷贝构造函数中发生的事情。
深拷贝会为拷贝的信息分配单独的内存,所以源目标和副本是相互独立的,在一个内存位置所做的任何更改都不会影响另一个位置的副本,当我们使用指针分配动态内存时,我们需要用户定义拷贝构造函数,这两个对象将指向不同的内存位置。
深拷贝的一般要求:
在前面的示例中,你可以看到当 c1 调用 concatenate()
时,c1 和 c2 都发生了变化,因为它们都指向同一个内存位置。
在下面的示例中,你可以看到用户定义的拷贝构造函数,即深拷贝构造函数。这里 c1 和 c2 都指向不同的内存位置,因此,在一个位置所做的更改不会影响另一个位置。
#include<iostream>
#include<cstring>
using namespace std;
class CopyConstructor
{
char *s_copy;
public:
CopyConstructor (const char *str)
{
s_copy = new char[16]; // 动态分配内存
strcpy(s_copy, str);
}
CopyConstructor (const CopyConstructor &str)
{
s_copy = new char[16]; // 动态分配内存
strcpy(s_copy, str.s_copy);
}
void concatenate(const char *str)
{
strcat(s_copy, str); // 连接两个字符串
}
~CopyConstructor()
{
delete [] s_copy;
}
void display()
{
cout<<s_copy<<endl;
}
};
int main()
{
CopyConstructor c1("Copy");
CopyConstructor c2 = c1; // 拷贝构造函数
c1.display();
c2.display();
c1.concatenate("Constructor"); //c1调用concatenate()
c1.display();
c2.display();
return 0;
}
以上实例输出结果:
Copy Copy CopyConstructor Copy