实现string大部分内容,在此,记录学习的点滴。
首先,实现普通版本的(这种容易理解,也不容易出错)
class String
{
public:
String()
:_str(new char[1])
{
_str='\0';
}
String(char* str = "")
:_str(new char[strlen(str)+1])
{
strcpy(_str, str);// \0 也拷贝了
}
String(const String& s)//必须自己写,否则会 浅拷贝
:_str(new char[strlen(s._str) + 1])
{
strcpy(_str, s._str);
}
String& operator=(const String& s)
{
if (this != &s)
{
char *tmp = new char[strlen(s._str) + 1];
delete[] _str;
strcpy(tmp, s._str);
_str = tmp;
}
return *this;
}
\
~String()
{
if (_str!= NULL)
delete[] _str; //free可以 free(NULL)
}
char* C_str()
{
return _str;
}
private:
char* _str;
};
其实,在后来的学习中,我也了解到 string的简洁版
//简洁版 String
class String
{
public:
String(char * str = "")// 给缺省参数 ‘\0'
:_str(new char[strlen(str) + 1])
{
strcpy(_str, str);
}
String(const String& s)
:_str(NULL) //保证tmp能正确析构
{
String tmp(s._str); //借用构造函数
std::swap(_str, tmp._str);
}
String& operator=(const String & s)
{
if (this != &s)
{
String tmp(s._str);
std::swap(_str, tmp._str);
}
return *this;
}
/*赋值 运算符更简洁版
String& operator=( String s)
{
std::swap(this->_str, s._str);
return *this;
}
*/
~String()
{
delete[] _str;
}
char *Cstr()
{
return _str;
}
char& operator[](size_t index)// 重载[]
{ //& 使它的 值可以改变
return _str[index];
}
public:
void PushBack(char ch)
{
}
private:
char *_str;
};
再后来,又想让多个对象控制一块字符串(一段空间),引入了引用计数版的string
在写引用计数之前,我也考虑到是否可以使用一个静态成员变量,对管理这个字符串的人数进行统计,事实证明,这是不可取的!
因为当我在重新创建一块新的对象并且管理一段新的字符串的时候,静态成员变量的值不是从原来自己设置的初值开始的,也就是静态成员变量的值会一直增加,而不会在没创建新的对象的时候还原为自己设定的初值。
这里就加深了 静态成员变量是属于类,而不属于对象本身,为所有对象共有的。
class String
{
public:
String(char* str = "")
:_str(new char[strlen(str)+1])
,_prefCount(new int(1))
{
strcpy(_str, str);
}
String( String& s) //没加 const
:_str(s._str)
, _prefCount(s._prefCount)
{
++*_prefCount;
//++(*s._prefCount)
}
String& operator=( String& s)
{
if (this != &s)
{
delete[] _str;
_str = NULL;
strcpy(_str, s._str);
*_prefCount = ++*(s._prefCount);
}
return *this;
}
~String()
{
if (!(-- *_prefCount)) //前置--
{
delete[] _str;
delete _prefCount; //也要释放
}
}
private:
char *_str;
int* _prefCount; //引用计数
};