本文概述
- 复制构造函数有两种类型
- 用户定义的复制构造函数的语法
- 调用复制构造函数时
- 构造函数生成两种类型的副本
- 浅拷贝
- 深拷贝
- 黑白复制构造函数和赋值运算符(=)的区别
复制构造函数有两种类型
- 默认副本构造函数:编译器定义默认副本构造函数。如果用户未定义副本构造函数, 则编译器将提供其构造函数。
- 用户定义的构造函数:程序员定义用户定义的构造函数。
文章图片
用户定义的复制构造函数的语法
Class_name(const class_name &
old_object);
请考虑以下情况:
class A
{
A(A &
x) //copy constructor.
{
// copyconstructor.
}
}
在上述情况下, 可以通过以下方式调用复制构造函数:
文章图片
【C++复制构造函数】让我们看一下复制构造函数的简单示例。
//复制构造函数的程序。
#include <
iostream>
using namespace std;
class A
{
public:
int x;
A(int a)// parameterized constructor.
{
x=a;
}
A(A &
i)// copy constructor
{
x = i.x;
}
};
int main()
{
A a1(20);
// Calling the parameterized constructor.
A a2(a1);
//Calling the copy constructor.
cout<
<
a2.x;
return 0;
}
输出:
20
调用复制构造函数时 在以下情况下将调用复制构造函数:
- 当我们使用另一个具有相同类类型的现有对象初始化该对象时。例如, 学生s1 = s2, 其中学生是班级。
- 当同一类类型的对象通过值作为参数传递时。
- 当函数按值返回相同类类型的对象时。
- 浅拷贝
- 深拷贝
- 默认副本构造函数只能生成浅表副本。
- 浅表副本定义为通过按原样复制所有成员变量的数据来创建对象副本的过程。
#include <
iostream>
using namespace std;
class Demo
{
int a;
int b;
int *p;
public:
Demo()
{
p=new int;
}
void setdata(int x, int y, int z)
{
a=x;
b=y;
*p=z;
}
void showdata()
{
std::cout <
<
"value of a is : " <
<
a<
<
std::endl;
std::cout <
<
"value of b is : " <
<
b<
<
std::endl;
std::cout <
<
"value of *p is : " <
<
*p<
<
std::endl;
}
};
int main()
{
Demo d1;
d1.setdata(4, 5, 7);
Demo d2 = d1;
d2.showdata();
return 0;
}
输出:
value of a is : 4
value of b is : 5
value of *p is : 7
文章图片
在上述情况下, 程序员尚未定义任何构造函数, 因此, 语句Demo d2 = d1; 调用编译器定义的默认构造函数。默认构造函数创建现有对象的精确副本或浅表副本。因此, 两个对象的指针p指向相同的存储位置。因此, 当一个字段的内存释放时, 另一个字段的内存也会自动释放, 因为两个字段都指向相同的存储位置。通过创建Deep复制的用户定义的构造函数可以解决此问题。
深拷贝 Deep Copy动态地为副本分配内存, 然后复制实际值, 源和副本都具有不同的内存位置。这样, 源和副本都是不同的, 并且不会共享相同的内存位置。深层复制要求我们编写用户定义的构造函数。
让我们通过一个简单的例子来理解这一点。
#include <
iostream>
using namespace std;
class Demo
{
public:
int a;
int b;
int *p;
Demo()
{
p=new int;
}
Demo(Demo &
d)
{
a = d.a;
b = d.b;
p = new int;
*p = *(d.p);
}
void setdata(int x, int y, int z)
{
a=x;
b=y;
*p=z;
}
void showdata()
{
std::cout <
<
"value of a is : " <
<
a<
<
std::endl;
std::cout <
<
"value of b is : " <
<
b<
<
std::endl;
std::cout <
<
"value of *p is : " <
<
*p<
<
std::endl;
}
};
int main()
{
Demo d1;
d1.setdata(4, 5, 7);
Demo d2 = d1;
d2.showdata();
return 0;
}
输出:
value of a is : 4
value of b is : 5
value of *p is : 7
文章图片
在上述情况下, 程序员已经定义了自己的构造函数, 因此语句Demo d2 = d1; 调用用户定义的复制构造函数。它创建值类型数据和指针p指向的对象的精确副本。深度复制不会创建引用类型变量的副本。
黑白复制构造函数和赋值运算符(=)的区别
复制构造函数 | 赋值运算符 |
---|---|
它是一个重载的构造函数。 | 它是按位运算符。 |
它使用现有对象初始化新对象。 | 它将一个对象的值分配给另一对象。 |
复制构造函数的语法:Class_name(const class_name&object_name){//构造函数的主体。 } | 赋值运算符的语法:Class_name a, b; b = a; |
使用现有对象初始化新对象时, 将调用复制构造函数。该对象作为参数传递给函数。它返回对象。 | 当我们将现有对象分配给新对象时, 将调用分配运算符。 |
现有对象和新对象都共享不同的内存位置。 | 现有对象和新对象都共享相同的内存位置。 |
如果程序员未定义副本构造函数, 则编译器将自动生成隐式默认副本构造函数。 | 如果我们不重载“ =”运算符, 则会出现按位复制。 |
推荐阅读
- C++析构函数剖析
- C++构造函数解析
- C++聚合(HAS-A关系)
- C++中的素数程序
- C++回文程序实例
- C++中的斐波那契数列
- C++中的析因程序
- C++与C#的区别
- C++向量vector用法