深浅拷贝
浅拷贝
string s1("hello world");
string s2(s1);
深拷贝
第一种写法:
string(const string& s)
:_str(new char[s.capacity+1])
,_size(s.szie())
,_capacity(s.capacity())
{
strcpy(_str,s._str);
}
//赋值时也会出现浅拷贝问题
//运算符重载 s1=s3
string& operator=(const string& s)
{
if(this!=&s)//避免自己给自己赋值
{
char*tmp=new[s._capacity+1];
strcpy(tmp,s._str);
delete[] _str;//释放赋值前s1的空间
_capacity=s._capacity;
_size=s._size;
_str=tmp;
}
return *this;
}
第二种写法:
//拷贝构造
//初始化列表的意义是 不让tmp里面都是随机值从而导致析构无法正常运行
string(const string&s)
:_str(nullptr)
,_size(0)
,_capacity(0)
{
string tmp(s._str);//调的是构造函数 会根据s._str的大小填充_size _capacity
swap(_str,tmp._str);
swap(_size,tmp._size);
swap(_capacity,tmp._capacity);
//swap(tmp);
}
//赋值
string& operator=(const string& s)
{
if(this!=&s)
{
//string tmp(s._str);
string tmp(s);//这里已经写好了拷贝构造 用什么都可以
swap(_str,tmp._str);
swap(_size,tmp._size);
swap(_capacity,tmp._capacity);
//swap(tmp);
}
return *this;
}
//赋值写法2
string& operator=(string s)
{
swap(s);
return *this;
}
//上述的swap可以复用
void swap(string& tmp)
{
//加::的意思是调用的是全局的swap函数 不是string类里面的 刚写的这个swap函数
//不写:: 调用时会现在类里面找 只能找到刚写的这个函数 而参数不匹配而发生报错
::swap(_str,tmp._str);
::swap(_size,tmp._size);
::swap(_capacity,tmp._capacity);
}
s1.swap(s2);//调用类里面的swap 这里成员全部交换
swap(s1,s2);//调用全局的swap 这里成员全部交换但srt的地址就不再是之前的两个中的了
构造析构
string(const char* str = "")
{
_size = strlen(str);
_capacity = _size;
_str = new char[_capacity + 1];
strcpy(_str, str);
}
~string()
{
delete[] _str;
_str = nullptr;
_size = _capacity = 0;
}
增删查改
插入
//扩容 ----size---代表存了几个数据 对应最后一个位置的下一个位置的下标
void reserve(size_t n)//这里n的含义是我需要存储的数据个数
{
if(n>capacity)
{
char*tmp=new char[n+1];//留一个给\0
strcpy(tmp,_str);
delete[] _str;
_str=tmp;
_capacity=n;
}
}
//插入字符
void push_back(char ch)
{
if(_size==_capacity)
{
reserve(_capacity==0?4;_capacity*2)//这里string构造函数中
//_capacity的初始值如果不是0可以不用三目
}
_str[_size]=ch;
_size++;
_str[_size]='\0';//这里一定要处理
}
//插入字符的 +=运算符重载
string& operator+=(char ch)
{
push_back(ch);
return *this;
}
//插入字符串
void append(const char*str)
{
size_t len=strlen(str);
//满了扩容
if(_size+len>_capacity)
{
reserve(_size+len);
}
strcpy(_str+size,str);//'\0'也拷贝过去
_size+=len;
}
//插入字符串的+=运算符重载
string& operator+=(const char*str)
{
append(str);
renturn *this;
}
// insert
string& insert(size_pos,char ch)//在pos位置插入一个字符
{
assert(pos<=_size);
if(_size==_capacity)
{
reserve(_capacity==0?4:_capacity*2);
}
//移数据
size_t end=_size+1;
while(end>pos)
{
_str[end]=_str[end-1];
--end;
}
_str[pos]=ch;
++size;
return *this;
}
string& insert(size_t pos,const char*str)//在pos位置插入一个字符串
{
assert(pos<=_size);
size_t len=strlen(str);
if(_size+len>_capacity)
{
reserve(_capacity==0?4:_capacity*2);
}
size_t end=_size+len;
while(end>=pos+len)
{
_str[end]=_str[end-len];
--end;
}
strncpy(_str+pos,str,len);//strcpy会把\0也拷贝过来
_size+=len;
return *this;
}
删除
class string
{
public:
void earse(size_t pos,size_t len= npos)//删除
{
assert(pos<_size);
if(len==npos||pos+len>=_size)//删的值很大
{
_str[pos]='\0';
_size=pos;
}
else
{
strcpy(_str+pos,_str+pos+len);
_size-=len;
}
}
static size_t npos;//声明
private:
size_t _capacity;
size_t _size;
char*_str;
}
size_t string::npos=-1;//定义
创建补充 也可以插入删除数据
//开空间+初始化
void resize(size_t n,char ch ='\0')//改变size 默认放\0
{
if(n>_size)
{
reserve(n);
for(size_t i=_size;i<n;i++)
{
_str[i]=ch;
}
_str[n]='\0';
_size=n;
}
else
{
_str[n]='\0';
_size=n;
}
}
查找
class string
{
public:
size_t find(char ch,size_t pos=0) const //pos为缺省值 不给就从零开始找
{
assetr(pos<_size);
for(size_t i=pos;i<_size;i++)
{
if(ch==_str[i])
{
return i;
}
}
return npos;
}
size_t find(const char*sub,size_t pos=0)const
{
assert(sub);
assert(pos<_size);
const char*ptr=strstr(_str+pos,sub);//C自带函数 strstr(起始位置,关键词)
//返回值为指针
if(ptr==nullptr)
return npos;
else
return ptr-_str;//指针减指针得下标
}
static size_t npos;
private:
size_t _capacity;
size_t _size;
char*_str;
}
size_t string::npos=-1;//定义
截取
string substr(size_t pos,size_t len = npos) const
{
assert(pos<_size);
size_t reallen=len;
if(len==npos||pos+len>_size)//截完了
{
reallen=_size-pos;
}
string sub;//存放截取数据做返回值的
for(size_t i=0;i<reallen;i++)
{
sub+=_srt[pos+i];
}
return sub;
}
流插入 流提取
class string
{
public:
size_t size() const
{
return _size;
}
void clear()
{
_str[0]='\0';
_size=0;
}
private:
size_t _capacity;
size_t _size;
char*_str;
};
ostream& operator<<(ostream& out, const string& s)
{
for(size_t i=0;i<s.size();i++)
{
out<<s[i];
}
}
istream& operator>>(istream& in,string& s)
{
char ch;
//in>>ch;会忽略空格和换行 导致不能结束输入
ch=in.get()
while(ch!=' '&&ch!='\n')//输入字符串很长时不断加等 扩容繁琐
{
s+=ch;
ch=in.get();
}
return in;
}
//流插入的优化
istream& operator>>(istream& in,string& s)//输入字符串时先存在其他地方再加等减少扩容
{
s.clear();
char ch;
ch=in.get();
const size_t N=32;
char buff[N];//存在于栈上 出作用域自动销毁
size_t i=0;
while(ch!=' '&&ch!='\n')
{
buff[i++]=ch;
if(i==N-1)//存满了
{
buff[i]='\0';
s+=buff;
i=0;
}
ch=in.get();//输入
}
buff[i]='\0';
s+=buff;
return in;
}
大小比较
bool operator>(const string& s) const
{
return strcmp(_str,s._str)>0;
}
bool operator==(const string& s)const
{
return strcmp(_str,s._str)==0;
}
bool operator>=(const string& s) const
{
return *this>s||*this==s;
}
bool operator<=(const string& s) const
{
return !*this>s;
}
bool operator<(const string& s) const
{
return !*this>=s;
}