string用法及stl库初解
std:string 的用法
三种方式:
- Eager Copy(深拷贝)
- COW(Copy-On -Write写时复制)
- SSO(Short String Optimization-短字符串优化
std:string都包含着:
- 字符串的大小
- 能够容纳的字符数量
- 字符串内容本身
写时复制
当执行复制构造或赋值时,引用计数加1,std::string对象共享字符串内容;当std::string对象销毁时,
并不直接释放字符串所在的空间,而是先将引用计数减1,直到引用计数为0时,则真正释放字符串内容
所在的空间。
#include<bits/stdc++.h>
using namespace std;
class String
{
private:
char *_pstr;//_pstr指向空间的首地址是字符串的第一个字符
void initRefcount(){
*(int*)(_pstr-4)=1;
}
void increaseRefcount(){
++*(int*)(_pstr-4);
}
void decreaseRefcount(){
--*(int*)(_pstr-4);
}
public:
String()
:_pstr(new char[1+4]()+4)
{
//初始化引用计数
initRefcount();
cout<<"String()"<<endl;
}
String(const char*pstr)
:_pstr(new char[strlen(pstr)+1]()+4)
{
cout<<"String(const char*)"<<endl;
initRefcount();
strcpy(_pstr,pstr);
}
String(const String &rhs)
:_pstr(rhs._pstr)
{
cout<<"String(const String &)"<<endl;
increaseRefcount();
}
String &operator=(const String &rhs){
if(this!=&rhs){
release();//释放左操作数的空间
//1:增加引用计数
//2: 浅拷贝
//3:
_pstr=rhs._pstr;//浅拷贝
increaseRefcount();
}
return *this;
}
int getRefcount() const { return *(int*)(_pstr - 4); }
void release(){
//引用计数-1,引用计数为0的时候释放对象
decreaseRefcount();
if(getRefcount()==0){
delete[](_pstr-4);
_pstr=nullptr;
cout<<">>>delete _pstr"<<endl;
}
}
~String(){
release();
cout<<"~String()"<<endl;
}
friend std::ostream & operator<<(std::ostream &os, const String &);
};
std::ostream & operator<<(std::ostream &os, const String & rhs)
{
os << rhs._pstr;
return os;
}
void test0(){
String str1;
cout<<"str1:"<<str1<<endl;
cout<<"str1's ref:"<<str1.getRefcount()<<endl;
String str2=str1;
cout<<"str2:"<<str2<<endl;
cout<<"str2's ref:"<<str2.getRefcount()<<endl;
String str3="hello world";
cout<<"str3:"<<str3<<endl;
String str4=str3;
cout<<"str4:"<<str4<<endl;
cout<<"str3.ref:"<<str3.getRefcount()<<endl;
cout<<"str4.ref"<<str4.getRefcount()<<endl;
cout<<endl;
String str5("wangdao");
cout<<"str5"<<str5<<endl;
cout<<"str5's ref:"<<str5.getRefcount()<<endl;
}
int main(){
test0();
return 0;
}
缺陷:
-
阻止了CPU的乱性执行.
-
两个CPU对同一个地址进行原子操作, 会导致cache失效, 从而重新从内存中读数据.
-
系统通常会lock住比目标地址更大的一片区域,影响逻辑上不相关的地址访问
最佳策略
1. 很短的(0~22)字符串用SSO,23字节表示字符串(包括'\0'),1字节表示长度
2. 中等长度的(23~255)字符串用eager copy,8字节字符串指针,8字节size,8字节capacity.
3. 很长的(大于255)字符串用COW, 8字节指针(字符串和引用计数),8字节size,8字节capacity.
STL模板库
vector创建对象库
void test0(){
// vector<int> number;//1、创建空对象
// vector<int> number(10,2);//2、count个value
vector<int> number={1,2,4,5,6,789,9,1,23};
for(size_t idx=0;idx!=number.size();idx++){//使用下标进行遍历
cout<<number[idx]<<" ";
}
cout<<endl;
for(auto &elem:number){//for加上auto遍历
cout<<elem<<" ";
}
cout<<endl;
vector<int>::iterator it;//使用迭代器进行遍历
for(it=number.begin();it!=number.end();it++){
cout<<*it<<" ";
}
cout<<endl;
for(auto it=number.begin();it!=number.end();it++){//auto it
cout<<*it<<" ";
}
cout<<endl;
}
插入元素过多可能导致迭代器失效
size()=t,capacity()=n,count个元素m
//1、m<n-t,不需要进行扩容
//2、n-t<m<t ,按照2*t进行扩容
//3、n-t<m && m>t ;按照t+m进行扩容
//4、n-t<m && m>n ;按照t+m进行扩容
push.back()可以一直插入
insert 插入的时候要考虑好扩容方式

浙公网安备 33010602011771号