String类:标准库类型string类表示可变长的字符序列,定义在std中,专门用来管理字符串,下面一起看下它的重要考点。
一:浅拷贝:
class String
{
public:
String(const char* pStr = "")//构造函数
:_pStr(new char[strlen(pStr)+1])
{
if(0 == *pStr)//字符串为空
{
*_pStr = '\0';
}
else//字符串不为空
{
strcpy(_pStr,pStr);
}
}
String(const String& s)//拷贝构造函数
{
_pStr = s._pStr;
}
String& operator=(String& s)//赋值运算符重载
{
if(_pStr != s._pStr)//判断是不是自己给自己赋值
{
_pStr = s._pStr;
}
return *this;
}
~String()//析构函数
{
if(NULL == _pStr)
{
return;
}
else
{
delete []_pStr;
_pStr = NULL;
}
}
private:
char* _pStr;
};
二:string四个版本的模拟实现:
1. 深拷贝普通版本
class string
{
public:
//构造函数
string(const char* ptr = "")
{
if (ptr == NULL)
{
_ptr = new char[1];
*_ptr = '\0';
}
_ptr = new char[strlen(ptr) + 1];
strcpy(_ptr, ptr);
}
//拷贝构造函数
string(const string& s)
:_ptr(new char[strlen(s._ptr)+1])
{
strcpy(_ptr, s._ptr);
}
string& operator=(const string& s)
{
if (this != &s)
{
char* tmp = new char[strlen(s._ptr) + 1];
strcpy(tmp, s._ptr);
delete[] _ptr;
_ptr = tmp;
}
return *this;
}
~string()
{
if (_ptr)
{
delete[] _ptr;
_ptr = NULL;
}
}
private:
char* _ptr;
};
2. 深拷贝简洁版
版本1:
class string
{
public:
//构造函数
string(const char* ptr = "")
{
if (ptr == NULL)
{
_ptr = new char[1];
*_ptr = '\0';
}
_ptr = new char[strlen(ptr) + 1];
strcpy(_ptr, ptr);
}
//拷贝构造函数
string(const string& s)
:_ptr(new char[strlen(s._ptr)+1])
{
strcpy(_ptr, s._ptr);
}
string& operator=(const string& s)
{
if (_ptr!=s.ptr)
{
delete[] _ptr;
_ptr = new char[strlen(s._ptr) + 1];
strcpy(_ptr, s._ptr);
}
return *this;
}
~string()
{
if (_ptr)
{
delete[] _ptr;
_ptr = NULL;
}
}
private:
char* _ptr;
};
版本2:
class string
{
public:
//构造函数
string(const char* ptr = "")
{
if (ptr == NULL)
{
_ptr = new char[1];
*_ptr = '\0';
}
_ptr = new char[strlen(ptr) + 1];
strcpy(_ptr, ptr);
}
//拷贝构造函数
string(const string& s)
:_ptr(NULL)
{
string tmp(s._ptr);
std::swap(_ptr, tmp._ptr);
}
string& operator=(const string& s)
{
if (_ptr!=s._ptr)
{
string tmp(s._ptr);
std::swap(_ptr,tmp._ptr);
}
return *this;
}
~string()
{
if (_ptr)
{
delete[] _ptr;
_ptr = NULL;
}
}
private:
char* _ptr;
};
3. 引用计数
class string
{
public:
//构造函数
string(const char* ptr = "")
:_count(new int[0])
, _ptr(new char[strlen(ptr)+1])
{
if (ptr == NULL)
{
_ptr = new char[1];
*_ptr = '\0';
}
else
strcpy(_ptr, ptr);
*_count = 1;
}
//拷贝构造函数
string(const string& s)
:_count(s._count)
{
_ptr = (char*)(s._ptr);
_count = s._count;
(*_count)++;
}
string& operator=(const string& s)
{
if (_ptr!=s._ptr)
{
_ptr = s._ptr;
_count = s._count;
(*_count)++;
}
return *this;
}
~string()
{
if (_ptr == NULL)
return;
else
{
if (--(*_count)==0)
{
delete[] _ptr;
delete[] _count;
_ptr = NULL;
_count = NULL;
}
}
}
private:
char* _ptr;
int* _count;
};
4. 写时拷贝
class string
{
public:
string(const char* ptr="")
:_ptr(new char[strlen(ptr)+4+1])//每次多创建4个空间来存放当前地址有几个对象
{
if (_ptr == NULL)
{
(*(int*)_ptr) = 1;//前四个字节拿来计数
_ptr += 4;
*_ptr = '\0';
}
else
{
(*(int*)_ptr) = 1;
_ptr += 4;
strcpy(_ptr, ptr);
}
}
string(const string& s)
:_ptr(s._ptr)
{
++(*(int*)(_ptr - 4));//向前偏移4个字节将计数加1
}
string& operator=(const string& s)
{
if (_ptr != s._ptr)
{
if (--(*(int*)(_ptr-4)) == 0)
{
delete[] _ptr;
_ptr = NULL;
}
_ptr = s._ptr;
++(*(int*)(_ptr - 4));
}
}
~string()
{
if (_ptr == NULL)
{
return;
}
else
{
if (--(*(int*)(_ptr - 4)) == 0)
{
delete[] (_ptr-4);
_ptr = NULL;
}
}
}
char& operator[](size_t index)//下标访问操作符重载
{
assert(index >= 0 && index < strlen(_ptr));
if ((*(int*)(_ptr - 4))>1)//多个对象指向同一块空间
{
char* tmp = new char[strlen(_ptr) + 4 + 1];//新开辟一块空间
tmp += 4;//向后偏移4
strcpy(tmp,_ptr);
--(*(int*)(_ptr - 4));//将原来空间的计数器减1
_ptr = tmp;//将当前对象指向临时空间
*((int*)(_ptr - 4)) = 1;//将新空间的计数器变为1
}
return _ptr[index];
}
private:
char* _ptr;
};