依然使用Student作为例子展开,其中CStudent(CStudent& stud) 就是拷贝构造函数,可以实现在使用类去初始话一个对象时,用同一个类的另外一个对象初始化。
class CStudent { public: char *p_name; char sex; int num; int age; CStudent(){}; CStudent(char* pname, char t_sex, int t_num, int t_age) :sex(t_sex), num(t_num), age(t_age) { p_name = NULL; int n_len = 0; if (pname) { n_len = strlen(pname); } if (n_len > 0) { p_name = new char[n_len + 1]; memset(p_name, 0, n_len + 1); strcpy(p_name, pname); } } CStudent(CStudent& stud) { strcpy(p_name, stud.p_name); num = stud.num; age = stud.age; } ~CStudent(); };在拷贝构造函数,加入对对应的析构函数后,程序如下所示,运行以下程序。
#include <iostream> #include <string> using namespace std; class CStudent { public: char *p_name; char sex; int num; int age; CStudent(){}; CStudent(char* pname, char t_sex, int t_num, int t_age) :sex(t_sex), num(t_num), age(t_age) { p_name = NULL; int n_len = 0; if (pname) { n_len = strlen(pname); } if (n_len > 0) { p_name = new char[n_len + 1]; memset(p_name, 0, n_len + 1); strcpy(p_name, pname); } } CStudent(CStudent& stud) { strcpy(p_name, stud.p_name); num = stud.num; age = stud.age; } ~CStudent(); }; CStudent::~CStudent() { if (p_name) { delete[] p_name; p_name = NULL; } } void test() { CStudent stud_1 = { "zhangsan",'m', 1001, 20 }; CStudent stud_2(stud_1); } int main(int argc, char* argv[]) { test(); return 0; }可能会出现以下报错 HEAP CORRUPTION DETECTED:before Free block(#0) at 0x008A4930.CRT detected that the application wrote to memory before start of heap buffer. _BLOCK_TYPE_IS_VALID(PhEAD->nBlockUse
由于出现问题,程序停止正常工作。windows将关闭程序,并会在有可用的解决方案时通知你。 原因:拷贝构造函数的p_name指针和源构造函数的p_name指针指向的是同一块内存,当第一次析构之后~CStudent已经完成析构,但是由于有拷贝构造函数的p_name指针也需要析构,就会出现异常。
解决方案就是在构建拷贝构造函数时,需要为新的指针开辟内存空间,防止两个指针指向同一块内存空间。
#include <iostream> #include <string> using namespace std; class CStudent { public: char *p_name; char sex; int num; int age; CStudent(){}; CStudent(char* pname, char t_sex, int t_num, int t_age) :sex(t_sex), num(t_num), age(t_age) { p_name = NULL; int n_len = 0; if (pname) { n_len = strlen(pname); } if (n_len > 0) { p_name = new char[n_len + 1]; memset(p_name, 0, n_len + 1); strcpy(p_name, pname); } } CStudent(const CStudent& stud) { int n_len = 0; n_len = strlen(stud.p_name); p_name = new char[n_len + 1]; memset(p_name, 0, n_len + 1); strcpy(p_name, stud.p_name); num = stud.num; age = stud.age; } ~CStudent(); }; CStudent::~CStudent() { if (p_name) { delete[] p_name; p_name = NULL; } } void test() { CStudent stud_1 = { "zhangsan",'m', 1001, 20 }; CStudent stud_2(stud_1); } int main(int argc, char* argv[]) { test(); return 0; }上面是使用重载构造函数解决问题,如果想使用以下命令去实现初始化
CStudent stud_2; stud_2 = stud_1;仍然使用上诉程序是会报和之前一样的错误,因为之前的幅值是函数赋值,现在是命令符赋值,这里就需要使用重载运算符。
CStudent& operator=(const CStudent& stud) { int n_len = 0; n_len = strlen(stud.p_name); p_name = new char[n_len + 1]; memset(p_name, 0, n_len + 1); strcpy(p_name, stud.p_name); num = stud.num; age = stud.age; return *this; }