我的码云
我的string码云
分析总结
1.项目结构
所有的类和函数
需要在namespace中实现
,要和string高度对应
private:
char* _str;//字符串
size_t _size;//有效长度
size_t _capacity;//总空间,包括'\0'
const static size_t npos=-1;
2.定义变量
<1>
所有的变量和函数要放到class中
,而且要规定private
类型
<2> 其中有一个是特殊的,const static size_t npos=-1
;这是需要特别记忆,size_t npos赋值为-1
,表示无符号整形的最大值
对于长度和总空间
一定不会是小于0的,我们依旧设为无符号整形
3.调试代码区域
因为这是在namespace中实现的,我们调试代码
可以需要加上using namespace
或者直接在namespace中写一个调试函数
4.构造函数
string()
:_str(new char[sizeof(char)*4]),
_size(0),
_capacity(4)
{
_str[0] = '\0';
}
在
对象初始化
的时候,我们首选初始化列表
进行初始化(效率更高),并且我们在初始化列表中,为了防止别人随便改变变量定义的顺序,导致初始化列表错乱,我们会选择在函数中进行初始化
。(初始化列表的初始化顺序并不是根据列表中数据出现的顺序决定的,而是由定义的顺序决定的)
string()
{
_size = 0;
_capacity = 4;
_str = new char[_capacity];
_str[0] = '\0';
}
在初始话的时候还要
注意变量的值要选取合适
,并且要注意字符串的结尾不论是有没有字符串都应该为'\0'
拷贝构造和析构函数
string(const string& other)
{
_size = other._size;
_capacity = other._capacity;
_str = new char[sizeof(char) * _capacity];
strcpy(_str, other._str);
}
~string()
{
delete[] _str;
}
代码中char数组需要设为动态的空间,要进行
深拷贝
,防止浅拷贝
带来的问题
在拷贝构造中要注意加const
,防止
传来的是匿名对象
,匿名对象有常性
,需要const修饰
才行,对于重载=也是需要加const
重载运算符
类内
friend ostream& operator<<(ostream& out, string& str);
friend istream& operator>>(istream& in, string& str);
类外
ostream& operator<<(ostream& out, string& str)
{
cout << str.c_str();
return out;
}
istream& operator>>(istream& in, string& str)
{
cin >> str._str;
return in;
}
等我回来再叙述iostream
因为这个是
<<和>>
必须要在类外实现,并且要调用类中private成员变量,我们必须使用friend标识符
我在<<调用的c_str()函数也就是说,我们的<<可以不用再类内声明成friend
也就是说,只有在需要调用类中的变量的时候才需要写成friend
迭代器
简单介绍
1.using namespace 的情况下
string::iterator it=str.begin();
2.没有使用using namespace 的定义形式
bit::string::iterator tem;
既要指明namespace又要指明class
实现
iterator是一个类型,他定义了it,it接收了begin()的返回值,it要对char数组进行访问,而且要能通过it自增进行连续的访问,那么it就应该是指针类型
char*
,同时又要写成iterator的形式,就需要进行typedef
typedef char* iterator;//必须要将这个定义放出来,不然类外就无法使用声明
iterator begin()
{
return _str;
}
iterator end()
{
return _str + _size + 1;
}
在写end函数的时候一定要清楚,end指向的是整个数组结尾的下一个位置
typedef char* iterator;这个定义一定要放到public中,不能放到private中,因为在外面进行定义迭代器的时候需要访问到iterator这个类型
::作用域操作符
,可以对类内public静态成员变量和函数
进行访问,以及上面这种类型
进行访问
reserve和resize
void resize(size_t n, char c = '\0')
{
delete[] _str;
_str = new char[sizeof(char) * (n + 1)];
_size = n;
_capacity = n + 1;
for (int i = 0; i < n; i++)
_str[i] = c;
_str[n] = '\0';
}
void reserve(size_t all)
{
int flag = 0;
while (all >= _capacity)
_capacity *= 2, flag = 1;
if (flag)
{
char* tem = _str;
_str = new char[_capacity];
strcpy(_str, tem);
}
}
reserve如果是缩小的话,不影响空间,不影响数据
resize如果是缩小的话,影响空间,影响数据
substr
string substr(size_t start=0, size_t n=npos) const
{
string ans;//临时变量,不能返回引用
if (start >= _size) return ans;
for (int i = start; i < start + n && i < _size; i++)
ans.push_back(_str[i]);
return ans;
}
在使用substr的时候,string ans;是临时变量,不能返回引用,虽然string内部的数组是动态开辟的,但是函数结束的时候,就会自动调用析构函数释放空间