class String
{
public:
String(const char *pStr = "")
{
/*
方法1:
if (NULL == pStr)
{
//空串
_str = new char[1];
*_str = '\0';
}
else
{
_str = new char[strlen(pStr) + 1];
strcpy(_str, pStr);
}
*/
//方法2:
if (pStr == NULL)
pStr = "";
_str = new char[strlen(pStr) + 1];
strcpy(_str, pStr);
}
~String()
{
if (_str)
delete[] _str;
}
private:
char *_str;
};
int main()
{
String str1("hello");
String str2(NULL);
String str3;
system("pause");
return 0;
}
浅拷贝
也称位拷贝,编译器只是将对象中的值采用基本类型值复制的方式拷贝过来,如果对象中管理资源,最后就会导致多个对象共享同一份资源,当一个对象销毁时就会将该资源释放掉,而此时另一些对象不知道该资源已经被释放, 以为还有效,所以当继续对资源进行操作时,就会发生访问违规
void Test()
{
String s1("hello");
//拷贝构造
String s2(s1);
String s3("world");
//赋值运算符重载
s1 = s3;
}
当类里面有指针对象时,拷贝构造和赋值运算符重载只进行值拷贝,两个对象共用同一块空间,对象销毁时程序会发生内存访问违规
//系统默认的拷贝构造和赋值运算符重载(反例)------程序崩溃
String(const String& s)
:_str(s._str)
{}
String &operator=(const String& s)
{
_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 (this != &s)
{
/*
//方法1:
delete[] _str;
_str = new char[strlen(s._str) + 1];
strcpy(_str, s._str);
*/
//方法2:
//先开空间,根据str的空间长度
char *pStr = new char[strlen(s._str) + 1];
//将str的内容复制到新的字串中
strcpy(pStr, s._str);
//将目标对象的字串删除
delete[] _str;
//将复制的新字串指给目标对象
_str = pStr;
}
return *this;
}
我们可以看到,s1、s2、s3三个空间,三个不同地址
实现String类的深拷贝的现代写法
//第一种写法,借助构造函数
String(const String& s)
:_str(NULL)//必须要注意初始化为空
{
String tmpstr(s._str);
swap(_str, tmpstr._str);
}
//第一种写法,借助构造函数
String &operator=(const String& s)
{
if (this != &s)
{
String tmpstr(s._str);
swap(_str, tmpstr._str);
}
return *this;
}
//第二种写法:借助拷贝构造函数
//必然会进行对象值拷贝操作(地址会变)
String &operator = (String s)//s已经是形参的临时变量
{
swap(_str, s._str);
return *this;
}
自定义类型&内置类型
template<class T>
void Copy(T*dst, T*src, size_t size, bool IsPODType)
{
if (IsPODType)
{
//优点:效率高 缺陷:浅拷贝
memcpy(dst, src, size*sizeof(T));
}
else
{
//优点:不会出错 缺点:效率低
for (size_t i = 0; i < size; i++)
dst[i] = src[i];
}
}
int main()
{
int arr1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
int arr2[10];
Copy(arr2, arr1, sizeof(arr1) / sizeof(arr1[0]), true);
//自定义类型,涉及深浅拷贝
string str1[] = { "1111", "2222", "3333", "4444" };
string str2[4];
Copy(str2, str1, sizeof(str1) / sizeof(str1[0]), false);
system("pause");
return 0;
}
类模板特化应用—类型萃取
#include <string>
//对应自定义类型
struct FalseType
{
static bool Get()
{
return false;
}
};
//对应内置类型
struct TrueType
{
static bool Get()
{
return true;
}
};
template<class T>
struct TypeTraits
{
typedef FalseType PODType;
};
template<>
struct TypeTraits<int>
{
typedef TrueType PODType;
};
template<>
struct TypeTraits<char>
{
typedef TrueType PODType;
};
template<class T>
void Copy(T*dst, T*src, size_t size)
{
if (TypeTraits<T>::PODType::Get())
{
//优点:效率高 缺陷:浅拷贝
memcpy(dst, src, size*sizeof(T));
}
else
{
//优点:不会出错 缺点:效率低
for (size_t i = 0; i < size; i++)
dst[i] = src[i];
}
}
int main()
{
int arr1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
int arr2[10];
Copy(arr2, arr1, sizeof(arr1) / sizeof(arr1[0]));
//自定义类型,设计深浅拷贝
string str1[] = { "1111", "2222", "3333", "4444" };
string str2[4];
Copy(str2, str1, sizeof(str1) / sizeof(str1[0]));
system("pause");
return 0;
}