原创博文,转载请标明出处--周学伟http://www.cnblogs.com/zxouxuewei/
1.什么是拷贝构造函数:
2.调用拷贝构造函数的情形:
(1)一个对象以值传递的方式传入函数体
#include <iostream>
#include <cstring>
using namespace std;
class test
{
public:
test();
test(const test& ctest);
~test();
private:
char Name;
};
test::test()
{
cout <<"Construction "<<endl;
}
test::test(const test& ctest)
{
cout <<"Copy Construction "<<endl;
}
test::~test()
{
cout <<"Destruction "<<endl;
}
void function(test param_test)
{
cout <<"into function"<<endl;
}
int main(int argc, char const *argv[])
{
test Atest;
function(Atest);
return 0;
}
运行结果
(2)一个对象以值传递的方式从函数返回
#include <iostream>
#include <cstring>
using namespace std;
class test
{
public:
test();
test(const test& ctest);
~test();
private:
char Name;
};
test::test()
{
cout <<"Construction "<<endl;
}
test::test(const test& ctest)
{
cout <<"Copy Construction "<<endl;
}
test::~test()
{
cout <<"Destruction "<<endl;
}
test function(test param_test)
{
cout <<"into function"<<endl;
return param_test;
}
int main(int argc, char const *argv[])
{
test Atest;
function(Atest);
return 0;
}
运行结果:
(3)一个对象需要通过另外一个对象进行初始化。
#include <iostream>
#include <cstring>
using namespace std;
class test
{
public:
test();
test(const test& ctest);
~test();
private:
char Name;
};
test::test()
{
cout <<"Construction "<<endl;
}
test::test(const test& ctest)
{
cout <<"Copy Construction "<<endl;
}
test::~test()
{
cout <<"Destruction "<<endl;
}
int main(int argc, char const *argv[])
{
test Atest;
test Btest = Atest;
return 0;
}
运行结果:
3.浅拷贝和深拷贝:
在某些状况下,类内成员变量需要动态开辟堆内存,如果实行位拷贝,也就是把对象里的值完全复制给另一个对象,如A=B。这时,如果B中有一个成员变量指针已经申请了内存,那A中的那个成员变量也指向同一块内存。这就出现了问题:当B把内存释放了(如:析构),这时A内的指针就是野指针了,出现运行错误。深拷贝和浅拷贝可以简单理解为:如果一个类拥有资源,当这个类的对象发生复制过程的时候,资源重新分配,这个过程就是深拷贝,反之,没有重新分配资源,就是浅拷贝。
---》深拷贝:(查看在堆上分配的内存资源进行深拷贝)
#include <iostream>
#include <cstring>
using namespace std;
class test
{
public:
test(char* name);
test(const test& ctest);
~test();
void Printf();
private:
char* PName;
};
test::test(char* name)//普通构造函数
{
if(name != NULL)
{
cout <<"Construction "<<name<<endl;
int len = strlen(name)+1;
PName = new char[len];
memset(PName, 0, len);
strcpy(PName,name);
}
else
{
PName = NULL;
}
cout <<"&PName = "<<static_cast<void*>(PName)<<endl;
}
test::test(const test& ctest)//深拷贝构造函数
{
if(ctest.PName != NULL)
{
cout <<"Copy Construction "<<endl;
int len = strlen(ctest.PName)+1;
PName = new char[len];
memset(PName, 0, len);
strcpy(PName,ctest.PName);
}
else
{
PName = NULL;
}
cout <<"&PName = "<<static_cast<void*>(PName)<<endl;
}
test::~test()
{
cout <<"Destruction "<<endl;
if(PName != NULL)
{
Printf();
delete []PName;
PName = NULL;
}
}
void test::Printf()
{
cout <<"&PName = "<<static_cast<void*>(PName)<<endl;
}
int main(int argc, char const *argv[])
{
test Atest((char*)"zhouxuewei");
test Btest = Atest;//复制对象的副本,此刻调用拷贝构造函数
return 0;
}
运行结果:
----》浅拷贝(使用编译器默认的拷贝构造函数)
#include <iostream> #include <cstring> using namespace std; class test { public: test(char* name); //test(const test& ctest); ~test(); void Printf(); private: char* PName; }; test::test(char* name)//普通构造函数 { if(name != NULL) { cout <<"Construction "<<name<<endl; int len = strlen(name)+1; PName = new char[len]; memset(PName, 0, len); strcpy(PName,name); } else { PName = NULL; } cout <<"&PName = "<<static_cast<void*>(PName)<<endl; } /* test::test(const test& ctest)//深拷贝构造函数 { if(ctest.PName != NULL)
{
cout <<"Copy Construction "<<endl;
int len = strlen(ctest.PName)+1;
PName = new char[len];
memset(PName, 0, len);
strcpy(PName,ctest.PName);
}
else
{
PName = NULL;
} cout <<"&PName = "<<static_cast<void*>(PName)<<endl; }*/ test::~test() { cout <<"Destruction "<<endl; if(PName != NULL) { Printf(); delete []PName; PName = NULL; } } void test::Printf() { cout <<"&PName = "<<static_cast<void*>(PName)<<endl; } int main(int argc, char const *argv[]) { test Atest((char*)"zhouxuewei"); test Btest = Atest;//复制对象的副本,此刻调用拷贝构造函数 return 0; }
运行结果:结果可以看出,拷贝的对象使用的堆内存地址相同,析构时free两次,产生错误:
4.赋值运算符
#include <iostream>
#include <cstring>
using namespace std;
class test
{
public:
test(char* name,int value);
test(const test& ctest);
~test();
test& operator=(const test& otest);
void Printf();
private:
char* PName;
int value;
static unsigned char count;
};
unsigned char test::count = 0;
test::test(char* name,int val)//普通构造函数
{
if(name != NULL)
{
int len = strlen(name)+1;
PName = new char[len];
memset(PName, 0, len);
strcpy(PName,name);
}
else
{
PName = NULL;
}
value = val;
cout <<"&PName = "<<static_cast<void*>(PName)<<", name = "<<PName<<", value = "<<value<<endl;
count++;
}
test::test(const test& ctest)//深拷贝构造函数
{
if(ctest.PName != NULL)
{
cout <<"Copy Construction "<<endl;
int len = strlen(ctest.PName)+1;
PName = new char[len];
memset(PName, 0, len);
strcpy(PName,ctest.PName);
}
else
{
PName = NULL;
}
cout <<"&PName = "<<static_cast<void*>(PName)<<", name = "<<PName<<endl;
count++;
}
test::~test()
{
cout <<"Destruction "<<", count = "<<static_cast<int>(count)<<endl;
if(PName != NULL)
{
Printf();
delete []PName;
PName = NULL;
}
count--;
}
test& test::operator=(const test& otest)
{
cout <<"into operator "<<endl;
if(&otest == this) //自赋值检查
{
return *this;
}
if(PName != NULL)
{
delete []PName; //原有资源的释放
PName = NULL;
}
if(otest.PName != NULL)
{
int len = strlen(otest.PName)+1;//开始赋值
PName = new char[len];
memset(PName, 0, len);
strcpy(PName, otest.PName);
}
else
PName = NULL;
value = otest.value;
return *this;
}
void test::Printf()
{
cout <<"&PName = "<<static_cast<void*>(PName)<<",name = "<<PName<<", value = "<<value<<endl;
}
int main(int argc, char const *argv[])
{
test Atest((char*)"zhouxuewei",111);
test Btest((char*)"wanghuixi",222);
Atest = Btest;
return 0;
}
运行结果:
总结:
1》何时需要定义拷贝构造函数:
a.类数据成员有指针。
b.类数据成员管理资源(如打开文件)
2》如果一个类需要析构函数来释放资源,则他需要一个拷贝构造函数。
3》如果想禁止一个类的拷贝构造,则需要将拷贝构造函数声明为private。