1.拷贝构造函数
1.1 拷贝构造函数定义
复制构造函数是构造函数的一种,也称拷贝构造函数,它只有一个参数,参数类型是本类的引用。
如果类的设计者不写复制构造函数,编译器就会自动生成复制构造函数。大多数情况下,其作用是实现从源对象到目标对象逐个字节的复制,即使得目标对象的每个成员变量都变得和源对象相等。编译器自动生成的复制构造函数称为“默认复制构造函数”。
注意:默认构造函数(即无参构造函数)不一定存在,但是复制构造函数总是会存在。
1.2 例子
#include <iostream>
class Text {
private:
int m_x;
int m_y;
public:
Text() { 默认构造函数
m_x = 0;
m_y = 0;
}
Text(int x,int y) { 带参数的构造函数
m_x = x;
m_y = y;
}
Text(const Text& another) { 显示默认复制构造函数
m_x = another.m_x;
m_y = another.m_y;
}
void PrintText() {
std::cout << "x = " << m_x << ",y = " << m_y << std::endl;
}
};
int main() {
Text t1;
t1.PrintText();
Text t2(t1); 会调用复制构造函数,将t1复制给t2
t2.PrintText();
}
输出结果
x = 0,y = 0
x = 0,y = 0
特别的
实例化对象时
Text t2 = t1; 也是调用默认复制构造函数
但是
Text t2;
t2 = t1; 调用的不是复制构造函数
原因:构造函数是对象初始化的时候调用
Text t2; 已经初始化完成,所以t2 = t1;调用的不是复制构造函数,而是t2的赋值操作符函数("="运算符的重载)
void operator=(const Text& another){
m_x = another.m_x;
m_y = another.m_y;
}
2.浅拷贝
2.1 浅拷贝定义
复制这个类的对象时,将复制其指针成员,但不复制指针指向的缓冲区,其结果是两个对象指向同一块动态分配的内存。销毁其中一个对象时,delete[]释放这个内存块,导致另一个对象存储的指针拷贝无效。这种复制被称为浅复制,会威胁程序的稳定性,
2.2 浅拷贝的例子
#include <iostream>
class Student {
private:
int m_id;
char *m_name;
public:
Student(int id,const char *name) {
std::cout << "调用Student(int id,char* name)……" << std::endl;
m_id = id;
m_name = (char*)malloc(strlen(name) + 1); //在栈上创建
//name = new char[strlen(name) + 1]; //在堆上创建
strcpy_s(m_name,sizeof(name), name);
}
void PrintS() {
std::cout << "ID = " << m_id << ", Name = " << m_name << std::endl;
}
~Student() { //析构函数
std::cout << "调用~Student()……" << std::endl;
if (m_name != NULL) {
free(m_name);
m_name = NULL;
}
}
};
int main() {
Student s1(1,"huajian");
s1.PrintS();
Student s2(s1); //调用默认拷贝构造函数
s2.PrintS();
return 0;
}
运行结果
调用Student(int id,char* name)……
ID = 1, Name = huajian
ID = 1, Name = huajain
调用~Student()……
调用~Student()……
浅拷贝与深拷贝.exe (进程 28484)已退出,代码为 -805306369。
原因:
3. 深拷贝
3.1 深拷贝的定义
复制这个类的对象时,深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。
3.2 深拷贝的实现
显示的提供一个拷贝构造函数,来完成深拷贝动作
Student(const Student& another) {
m_id = another.m_id;
m_name = (char*)malloc(strlen(another.m_name) + 1);
strcpy_s(m_name, sizeof(m_name), another.m_name);
}