拷贝有两种:深拷贝,浅拷贝
当出现类的等号赋值时,会调用拷贝函数。在未定义显示拷贝构造函数的情况下,系统会调用默认某种拷贝函数,由系统决定是浅拷贝还是深拷贝。浅拷贝能够完成成员的复制。当数据成员中没有指针时,浅拷贝是可行的。当数据成员中有指针时,如果采用简单的浅拷贝,则两类中的两个指针将指向同一个地址,当对象快结束时,会调用两次析构函数,而导致指针悬挂现象。在这种情况下可以通过引用计数的浅拷贝来实现。
下面代码为String类的简单浅拷贝,深拷贝的传统写法和现代写法。
#include<iostream>
using namespace std;
class String
{
public:
String(char* str = "")//对于string s;用""表示空
:_str(new char[strlen(str) + 1])
{
strcpy(_str, str);
}
//-----------------------------------------------
//简单的赋值浅拷贝
//String(const String& s)
//:_str(s._str)
//{}
//赋值运算符重载
//String& operator=(const String& s)
//{
//if (_str != s._str)
//{
//strcpy(_str, s._str);
//}
//return *this;
//}
//深拷贝
//-----------------------------------------------
//深拷贝的传统写法
//String(const String& s)
//:_str(new char[strlen(s._str) + 1])
//{
//strcpy(_str, s._str);
//}
////赋值运算符重载
//String& operator=(const String& s)
//{
//if (_str != s._str)
//{//先释放后指向,否则_str无人管理会内存泄漏
////delete[] _str;//_str占内存较小1
////_str = new char[strlen(s._str) + 1];//s._str占内存较大1000000,会失败
////strcpy(_str,s._str);
//char* tmp = new char[strlen(s._str) + 1];
//strcpy(tmp, s._str);
//delete[] _str;
//_str = tmp;
//}
//return *this;
//}
//-----------------------------------------------
//深拷贝的现代写法
String (const String& s)
: _str(NULL)//防止释放有随机值的空间出错
{
String tmp = s._str;
swap(tmp._str, _str);
}
//赋值运算符重载
//String& operator=(const String& s)
//{
// if (_str != s._str)
// {
// String tmp(s._str);
// swap(tmp._str,_str);
// }
// return *this;
//}
String& operator=(String s)
{
if (_str != s._str)
{
swap(_str,s._str);
}
return *this;
}
//同一空间被多次释放
~String()
{
if (_str)
{
cout << "~String()" << endl;
delete[] _str;
}
}
void put()
{
cout << _str << endl;
}
private:
char* _str;
};
void Test()
{
String s;
String s1("");
String s2(s1);
String s3 = s1;
s.put();
s1.put();
s2.put();
s3.put();
}
int main()
{
Test();
system("pause");
return 0;
}
对于引用计数的浅拷贝见本人博客:
【String类的引用计数的浅拷贝】http://10741357.blog.51cto.com/10731357/1747871
本文出自 “Scen” 博客,请务必保留此出处http://10741357.blog.51cto.com/10731357/1747867