系统提供默认的拷贝构造器,一经定义不再提供。但系统提供的默认拷贝构造器是 等位拷贝,也就是通常意义上的浅拷贝。如果类中包含的数据元素全部在栈上,浅拷贝 也可以满足需求的。但如果堆上的数据,则会发生多次析构行为。
#include <iostream>
#include <cstdlib>
using namespace std;
int strlen(const char s[]){
int len = 0;
while (s[len]){
len++;
}
return len; // 返回数组str中首个值为null的元素的下标值
}
char* strcpy(char *p, const char *s){
char *t = p;
while (*p++ = *s++){
}
return t;
}
class Teacher{
public:
//有参数的构造函数
Teacher(int id, const char *name){
cout << "调用了Teacher 的构造函数" << endl;
//是给id 赋值
m_id = id;
//给姓名赋值
int len = strlen(name);
m_name = (char*)malloc(len + 1);
strcpy(m_name, name);
}
//显示写一个拷贝构造函数
//通过显示拷贝构造函数提供了深拷贝的动作
Teacher(const Teacher &another){
m_id = another.m_id; //给id赋值
int len = strlen(another.m_name);
m_name = (char*)malloc(len + 1);
strcpy(m_name, another.m_name);
}
~Teacher() {
//在构造函数中, 已经开辟了内存 所以为了防止泄露
//在析构函数中,在对象销毁之前,把m_name的内存释放掉
if (m_name != NULL) {
free(m_name);
m_name = NULL;
cout << "释放掉了m_name" << endl;
}
}
private:
int m_id;
char *m_name;
};
int main(void){
Teacher t1(1, "vvcat");
//如果不提供一个显示的拷贝构造函数, 通过系统自带的默认拷贝构造函数
Teacher t2(t1); //会调用t2的拷贝构造函数,将t1的值拷贝给t2
}
注:
- 当类中声明的成员变量有char *时,在变量调用有参函数或无参函数进行初始化的时候,需要对成员变量开辟一个存储该变量的空间,如果在后续的操作中,有调用
拷贝构造函数
需要对变量进行深拷贝的动作
,为拷贝后的变量开辟一个新的空间,使拷贝变量和被拷贝变量的空间互不影响。
如果在拷贝构造函数
没有对变量进行深拷贝
的动作而使用了浅拷贝
的动作,程序会报错或者会因为 char * 变量因为没有得到释放,导致程序崩溃。
以下是,错误举例:
Teacher(const Teacher &another){
m_id = another.m_id; //给id赋值
m_name = another.m_name; // 这里会使程序报错
}
- Teacher(int id, const char *name) 中,在一些编译器中省略
const
会出现报错,而在一些编译器中会出现 警告的提示,所以一般在编写代码中尽量不要省略。 深拷贝
可以防止重复释放同一块内存和内存的泄漏。