目录
区分对象的复制与对象的赋值
// 在定义的同时初始化被称为拷贝
Cstudent stud1 = stud2; // 也可以写成:stud1(stud2)
// 在定义之后初始化被称为复制
Cstudent stud1;
stud1 = stud2;
解析“深拷贝”与“浅拷贝”
浅拷贝
浅拷贝简介
浅拷贝是指源对象与拷贝对象共用一份实体,仅仅是引用的变量不同(名称不同)。对其中任何一个对象的改动都会影响另外一个对象。举个例子,一个人一开始叫张三,后来改名叫李四了,可是还是同一个人,不管是张三缺胳膊少腿还是李四缺胳膊少腿,都是这个人倒霉。
适用情况
类对象的成员变量中无指针类型的变量。
当程序中有指针变量时出现错误
#include <iostream>
using namespace std;
#include<string>
class Cstudent
{
private:
int mark;
char *name;
public:
Cstudent(int mark, char *name)
{
int i = strlen(name);
this->name = new char[i + 1]; //+1是为了存储字符串的'\0'
memset(this->name, 0, i + 1);
strcpy(this->name, name);
this->mark = mark;
}
Cstudent(Cstudent &stud) // 拷贝构造函数形参是该类对象的引用
{
strcpy(this->name, stud.name);
this->mark = stud.mark;
}
~Cstudent()
{
if (this->name)
{
delete[] this->name;
}
cout << "调用析构函数进行收尾工作" << endl;
}
void out()
{
cout << name << endl;
}
};
int main()
{
char str[] = "超级无敌霸霸强";
Cstudent stud1(89, str);
Cstudent stud2(stud1); // 对象拷贝
stud2.out();
stud1.out();
}
错误如下:
为什么会出现报错呢?
因为浅拷贝与复制仅仅是复制了一下指针中的地址,编译时一般没事,但是当内存释放时就有问题了,同样的地址释放两次,那必须报错呀!
深拷贝
深拷贝简介
深拷贝是指源对象与拷贝对象互相独立,其中任何一个对象的改动都不会对另外一个对象造成影响。举个例子,一个人名叫张三,后来用他克隆(假设法律允许)了另外一个人,叫李四,不管是张三缺胳膊少腿还是李四缺胳膊少腿都不会影响另外一个人。
适用情况
对于一切情况均适用
程序如下
#include <iostream>
using namespace std;
#include<string>
class Cstudent
{
private:
int mark;
char *name;
public:
Cstudent(int mark, char *name)
{
int i = strlen(name);
this->name = new char[i + 1]; //+1是为了存储字符串的'\0'
memset(this->name, 0, i + 1);
strcpy(this->name, name);
this->mark = mark;
}
Cstudent(Cstudent &stud) // 拷贝构造函数形参是该类对象的引用
{
int i = strlen(stud.name);
this->name = new char[i + 1]; // 深拷贝使得拷贝函数不是简单的复制对象stud.name的地址,而是执行了值传递
strcpy(this->name, stud.name);
this->mark = stud.mark;
}
~Cstudent()
{
if (this->name)
{
delete[] this->name;
}
cout << "调用析构函数进行收尾工作" << endl;
}
void out()
{
cout << name << endl;
}
};
int main()
{
char str[] = "超级无敌霸霸强";
Cstudent stud1(89, str);
Cstudent stud2(stud1); // 对象拷贝
stud2.out();
stud1.out();
}
两者不同点仅在于拷贝函数
浅拷贝:
Cstudent(Cstudent &stud) // 拷贝构造函数形参是该类对象的引用
{
strcpy(this->name, stud.name);
this->mark = stud.mark;
}
深拷贝:
Cstudent(Cstudent &stud) // 拷贝构造函数形参是该类对象的引用
{
int i = strlen(stud.name);
this->name = new char[i + 1]; // 深拷贝使得拷贝函数不是简单的复制对象stud.name的地址,而是执行了值传递
strcpy(this->name, stud.name);
this->mark = stud.mark;
}
我们看到在深拷贝中我们动态申请了空间用于盛放地址对应的值,是典型的值传递,变量地址之间的传递是典型的引用。我们要的是数值,地址对应的值,不是地址,要地址没什么用处!