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 插入的时候要考虑好扩容方式
posted @ 2022-04-19 19:39  Fancele  阅读(154)  评论(0)    收藏  举报