String:利用引用计数进行实现
利用引用计数的实现方式
#include <iostream>
#include <cstring>
#include <iomanip>
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
using namespace std;
class StringBuf{
public:
StringBuf():buf(0),len(0),used(0),refs(1){}
// StringBuf(int n):buf(new char[n]),len(1.5*n),used(0),refs(1){ }
StringBuf(int n):buf(0),len(0),used(0),refs(1){
Reserve(n);
}
StringBuf(const StringBuf& other,size_t n=0);
~StringBuf(){delete[] buf;}
void Reserve(size_t n);
char *buf;
size_t len;
size_t used;
unsigned refs;
private:
// StringBuf(const StringBuf&);
StringBuf& operator=(const StringBuf&);
};
StringBuf::StringBuf(const StringBuf& other,size_t n):
buf(0),len(0),used(0),refs(1){
Reserve(max(other.len,n));
strncpy(buf,other.buf,other.used);
used=other.used;
}
void StringBuf::Reserve(size_t n){
if(len<n){
size_t needed=max<size_t>(len*1.5,n);
size_t newlen=needed?4*((needed-1)/4+1):0;
char *newbuf=newlen?new char[newlen]:0;
if(buf){
strncpy(newbuf,buf,used);
}
delete[] buf;
buf=newbuf;
len=newlen;
}
}
class String{
friend istream& operator>>(istream&,String&);
friend ostream& operator<<(ostream&,const String&);
friend String operator+(const String&,const String&);
friend String operator+(const String&,const char*);
public:
String();
String(int,char);
String(const char*);
String(const String&);
~String();
String& operator=(const String&);
String& operator=(const char*);
String& operator+=(const String&);
String& operator+=(const char*);
String& operator+=(const char&);
bool operator==(const String &)const;
bool operator!=(const String &)const;
bool operator>(const String &)const;
bool operator>=(const String &)const;
bool operator<(const String &)const;
bool operator<=(const String &)const;
bool operator==(const char*)const;
bool operator!=(const char*)const;
bool operator>(const char*)const;
bool operator>=(const char*)const;
bool operator<(const char*)const;
bool operator<=(const char*)const;
char& operator[](size_t );
const char operator[](size_t)const;
size_t size()const{
return data_->used;
}
char* c_str();
// private:
void AboutToModify(size_t n,bool bUnshareable=false);
const static size_t Unshareable;
StringBuf* data_;
};
const size_t String::Unshareable=100;
String::~String(){
if(data_->refs==Unshareable||--data_->refs<1)
delete data_;
}
String::String():data_(new StringBuf){}
String::String(int n,char ch):data_(new StringBuf(n)){
for(int i=0;i<n;i++)
data_->buf[i]=ch;
data_->used=n;
}
String::String(const char*str){
if(!str)
data_=new StringBuf();
else{
size_t n=strlen(str);
data_=new StringBuf(n);
strncpy(data_->buf,str,n);
data_->used=n;
}
}
String::String(const String& other){
if(other.data_->refs!=Unshareable){
data_=other.data_;
++data_->refs;
}
else{
data_=new StringBuf(*other.data_);
}
}
void String::AboutToModify(size_t n,bool markUnshareable){
if(data_->refs>1&&data_->refs!=Unshareable){
StringBuf* newdata=new StringBuf(*data_,n);
--data_->refs;
data_=newdata;
}
else{
data_->Reserve(n);
}
data_->refs=markUnshareable?Unshareable:1;
}
String& String::operator=(const String& str){
if(this!=&str){
if(data_->refs==Unshareable||--data_->refs<1)
delete data_;
if(str.data_->refs!=Unshareable){
data_=str.data_;
++data_->refs;
}
else{
data_=new StringBuf(*str.data_);
}
}
return *this;
}
String& String::operator=(const char*str){
if(!str) {
data_=NULL;
}
else{
size_t n=strlen(str);
AboutToModify(n,false);
strncpy(data_->buf,str,n);
data_->used=n;
}
return *this;
}
String& String::operator+=(const String& str){
if(str.size()==0)
return *this;
size_t n=str.size();
AboutToModify(data_->used+n,false);
strncpy(data_->buf+data_->used,str.data_->buf,n);
data_->used+=n;
// if(data_.refs==1){
// data_.Reserve(data_->used+n);
// strncpy(data_->buf+data_->used,str.data_->buf,n);
// data_->used+=n;
// }
// else{
// free();
// StringBuf* tmp=new StringBuf(data_->used+n);
// strncpy(tmp.buf,str.data_->buf,data_->used);
// strncpy(tmp.buf+data_->used,str.data_->buf,n);
// tmp.used=data_->used+n;
// data_=tmp;
// }
return *this;
}
String& String::operator+=(const char *str){
if(!str)
return *this;
size_t n=strlen(str);
AboutToModify(data_->used+n,false);
strncpy(data_->buf+data_->used,str,n);
data_->used+=n;
// if(data_.refs==1){
// data_.Reserve(data_->used+n);
// strncpy(data_->buf+data_->used,str,n);
// data_->used+=n;
// }
// else{
// free();
// StringBuf* tmp=new StringBuf(data_->used+n);
// strncpy(tmp.buf,str.data_->buf,data_->used);
// strncpy(tmp.buf+data_->used,str,n);
// tmp.used=data_->used+n;
// data_=tmp;
// }
return *this;
}
String& String::operator+=(const char& c){
AboutToModify(data_->used+1,false);
data_->buf[data_->used++]=c;
// if(data_.refs==1){
// data_.Reserve(data_->used+1);
// data_->buf[data_->used++]=c;
// }
// else{
// free();
// StringBuf* tmp=new StringBuf(data_->used+1);
// strncpy(tmp.buf,str.data_->buf,data_->used);
// tmp.buf[data_->used+1]=c;
// tmp.used=data_->used+1;
// data_=tmp;
// }
}
bool String::operator==(const String& str)const{
if(data_->buf==str.data_->buf)
return true;
else if(data_->used==str.data_->used)
return strncmp(data_->buf,str.data_->buf,data_->used)==0?true:false;
else
return false;
}
bool String::operator!=(const String& str)const{
return !(*this==str);
}
bool String::operator>(const String& str)const{
if(data_->buf==str.data_->buf)
return false;
else if(data_->used==str.data_->used)
return strncmp(data_->buf,str.data_->buf,data_->used)>0?true:false;
else{
int n=min(data_->used,str.data_->used);
int cmp=strncmp(data_->buf,str.data_->buf,n);
if(cmp==0)
return data_->used<str.data_->used;
else
return cmp>0;
}
}
bool String::operator>=(const String&str)const{
return *this==str||*this>str;
}
bool String::operator<(const String& str)const{
return !(*this>str);
}
bool String::operator<=(const String& str)const{
return *this==str||*this<str;
}
bool String::operator==(const char *str)const{
size_t n=strlen(str);
if(data_->used==n)
return strncmp(data_->buf,str,data_->used)==0?true:false;
else
return false;
}
bool String::operator!=(const char *str)const{
return !(*this==str);
}
bool String::operator>(const char* str)const{
size_t sz=strlen(str);
if(data_->used==sz)
return strncmp(data_->buf,str,data_->used)>0?true:false;
else{
int n=min(data_->used,sz);
int cmp=strncmp(data_->buf,str,n);
if(cmp==0)
return data_->used<sz;
else
return cmp>0;
}
}
bool String::operator>=(const char* str)const {
return *this==str||*this>str;
}
bool String::operator<(const char* str)const {
return !(*this>str);
}
bool String::operator<=(const char* str)const {
return *this==str||*this<str;
}
char& String::operator[](size_t n){
AboutToModify(data_->len,false);
return data_->buf[n];
}
const char String::operator[](size_t n)const{
return data_->buf[n];
}
String operator+(const String& str1,const String& str2){
if(str1.data_->used==0&&str2.data_->used==0)
return String();
else if(str1.data_->used==0&&str2.data_->used!=0){
return String(str2);
}
else if(str1.data_->used!=0&&str2.data_->used==0){
return String(str1);
}
else{
String newstr;
newstr.AboutToModify(str1.data_->used+str1.data_->used,false);
strncpy(newstr.data_->buf,str1.data_->buf,str1.data_->used);
strncpy(newstr.data_->buf+str1.data_->used,str2.data_->buf,str2.data_->used);
newstr.data_->used=str1.data_->used+str2.data_->used;
return newstr;
}
}
String operator+(const String&str1,const char*str2) {
size_t len=strlen(str2);
if(str1.data_->used==0&&len==0)
return String();
else if(str1.data_->used==0&&len!=0){
return String(str2);
}
else if(str1.data_->used!=0&&len==0){
return String(str1);
}
else{
String newstr;
newstr.AboutToModify(str1.data_->used+len,false);
strncpy(newstr.data_->buf,str1.data_->buf,str1.data_->used);
strncpy(newstr.data_->buf+str1.data_->used,str2,len);
newstr.data_->used=str1.data_->used+len;
return newstr;
}
}
istream& operator>>(istream& is,String& str){
const int limit_string_used=4096;
char inBuf[limit_string_used];
is>>setw(limit_string_used)>>inBuf;
str=inBuf;
return is;
}
ostream& operator<<(ostream& os,const String& str){
for(int i=0;i<str.data_->used;i++)
os<<str.data_->buf[i];
return os;
}
int main1()
{
int aCnt = 0, eCnt = 0, iCnt = 0, oCnt = 0, uCnt = 0,
theCnt = 0, itCnt = 0, wdCnt = 0, notVowel = 0;
// 为了使用 operator==( const char* )
// 我们并不定义 The( "The" )和 It( "It" )
String buf, the( "the" ), it( "it" );
// 调用 operator>>( istream&, String& )
while ( cin >> buf ) {
++wdCnt;
// 调用 operator<<( ostream&, const String& )
cout << buf << ' ';
if ( wdCnt % 12 == 0 )
cout << endl;
// 调用 String::operator==(const String&) and
//
if ( buf == the || buf == "The" )
++theCnt;
if ( buf == it || buf == "It" )
++itCnt;
// 调用 String::size()
for ( int ix = 0; ix < buf.size(); ++ix )
{
// 调用 String::operator[](int)
switch( buf[ ix ] )
{
case 'a': case 'A': ++aCnt;
break;
case 'e': case 'E': ++eCnt;
break;
case 'i': case 'I': ++iCnt;
break;
case 'o': case 'O': ++oCnt;
break;
case 'u': case 'U': ++uCnt;
break;
default: ++notVowel; break;
}
}
}
// 调用 operator<<( ostream&, const String& )
cout << "\n\n"
<<"Words read: " << wdCnt << "\n\n"
<<"the/The: " << theCnt << '\n'
<<"it/It: " << itCnt << "\n\n"
<<"non-vowels read: " << notVowel << "\n\n"
<<"a: " << aCnt << '\n'
<<"e: " << eCnt << '\n'
<<"i: " << iCnt << '\n'
<<"o: " << oCnt << '\n'
<<"u: " << uCnt << endl;
String a="hello";
String b="world";
String c=a+b;
cout<<c<<endl;
return 0;
}
int main(){
String s="abc";
cout<<s.data_->refs<<endl;
String s2="abc";
cout<<s2.data_->refs<<endl;
s+="dd";
String s3=s+s2;
cout<<s3<<endl;
cout<<s3.data_->refs<<endl;
String s4(s3);
cout<<s4<<endl;
cout<<s4.data_->refs<<endl;
cout<<s3.data_->refs<<endl;
s4[1]='x';
cout<<s4<<endl;
cout<<s4.data_->refs<<endl;
cout<<s3.data_->refs<<endl;
String s5(s4);
cout<<s5<<endl;
cout<<s5.data_->refs<<endl;
cout<<s4.data_->refs<<endl;
cout<<s3<<endl;
cout<<s3.data_->refs<<endl;
}
#include <cstring>
#include <iomanip>
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
using namespace std;
class StringBuf{
public:
StringBuf():buf(0),len(0),used(0),refs(1){}
// StringBuf(int n):buf(new char[n]),len(1.5*n),used(0),refs(1){ }
StringBuf(int n):buf(0),len(0),used(0),refs(1){
Reserve(n);
}
StringBuf(const StringBuf& other,size_t n=0);
~StringBuf(){delete[] buf;}
void Reserve(size_t n);
char *buf;
size_t len;
size_t used;
unsigned refs;
private:
// StringBuf(const StringBuf&);
StringBuf& operator=(const StringBuf&);
};
StringBuf::StringBuf(const StringBuf& other,size_t n):
buf(0),len(0),used(0),refs(1){
Reserve(max(other.len,n));
strncpy(buf,other.buf,other.used);
used=other.used;
}
void StringBuf::Reserve(size_t n){
if(len<n){
size_t needed=max<size_t>(len*1.5,n);
size_t newlen=needed?4*((needed-1)/4+1):0;
char *newbuf=newlen?new char[newlen]:0;
if(buf){
strncpy(newbuf,buf,used);
}
delete[] buf;
buf=newbuf;
len=newlen;
}
}
class String{
friend istream& operator>>(istream&,String&);
friend ostream& operator<<(ostream&,const String&);
friend String operator+(const String&,const String&);
friend String operator+(const String&,const char*);
public:
String();
String(int,char);
String(const char*);
String(const String&);
~String();
String& operator=(const String&);
String& operator=(const char*);
String& operator+=(const String&);
String& operator+=(const char*);
String& operator+=(const char&);
bool operator==(const String &)const;
bool operator!=(const String &)const;
bool operator>(const String &)const;
bool operator>=(const String &)const;
bool operator<(const String &)const;
bool operator<=(const String &)const;
bool operator==(const char*)const;
bool operator!=(const char*)const;
bool operator>(const char*)const;
bool operator>=(const char*)const;
bool operator<(const char*)const;
bool operator<=(const char*)const;
char& operator[](size_t );
const char operator[](size_t)const;
size_t size()const{
return data_->used;
}
char* c_str();
// private:
void AboutToModify(size_t n,bool bUnshareable=false);
const static size_t Unshareable;
StringBuf* data_;
};
const size_t String::Unshareable=100;
String::~String(){
if(data_->refs==Unshareable||--data_->refs<1)
delete data_;
}
String::String():data_(new StringBuf){}
String::String(int n,char ch):data_(new StringBuf(n)){
for(int i=0;i<n;i++)
data_->buf[i]=ch;
data_->used=n;
}
String::String(const char*str){
if(!str)
data_=new StringBuf();
else{
size_t n=strlen(str);
data_=new StringBuf(n);
strncpy(data_->buf,str,n);
data_->used=n;
}
}
String::String(const String& other){
if(other.data_->refs!=Unshareable){
data_=other.data_;
++data_->refs;
}
else{
data_=new StringBuf(*other.data_);
}
}
void String::AboutToModify(size_t n,bool markUnshareable){
if(data_->refs>1&&data_->refs!=Unshareable){
StringBuf* newdata=new StringBuf(*data_,n);
--data_->refs;
data_=newdata;
}
else{
data_->Reserve(n);
}
data_->refs=markUnshareable?Unshareable:1;
}
String& String::operator=(const String& str){
if(this!=&str){
if(data_->refs==Unshareable||--data_->refs<1)
delete data_;
if(str.data_->refs!=Unshareable){
data_=str.data_;
++data_->refs;
}
else{
data_=new StringBuf(*str.data_);
}
}
return *this;
}
String& String::operator=(const char*str){
if(!str) {
data_=NULL;
}
else{
size_t n=strlen(str);
AboutToModify(n,false);
strncpy(data_->buf,str,n);
data_->used=n;
}
return *this;
}
String& String::operator+=(const String& str){
if(str.size()==0)
return *this;
size_t n=str.size();
AboutToModify(data_->used+n,false);
strncpy(data_->buf+data_->used,str.data_->buf,n);
data_->used+=n;
// if(data_.refs==1){
// data_.Reserve(data_->used+n);
// strncpy(data_->buf+data_->used,str.data_->buf,n);
// data_->used+=n;
// }
// else{
// free();
// StringBuf* tmp=new StringBuf(data_->used+n);
// strncpy(tmp.buf,str.data_->buf,data_->used);
// strncpy(tmp.buf+data_->used,str.data_->buf,n);
// tmp.used=data_->used+n;
// data_=tmp;
// }
return *this;
}
String& String::operator+=(const char *str){
if(!str)
return *this;
size_t n=strlen(str);
AboutToModify(data_->used+n,false);
strncpy(data_->buf+data_->used,str,n);
data_->used+=n;
// if(data_.refs==1){
// data_.Reserve(data_->used+n);
// strncpy(data_->buf+data_->used,str,n);
// data_->used+=n;
// }
// else{
// free();
// StringBuf* tmp=new StringBuf(data_->used+n);
// strncpy(tmp.buf,str.data_->buf,data_->used);
// strncpy(tmp.buf+data_->used,str,n);
// tmp.used=data_->used+n;
// data_=tmp;
// }
return *this;
}
String& String::operator+=(const char& c){
AboutToModify(data_->used+1,false);
data_->buf[data_->used++]=c;
// if(data_.refs==1){
// data_.Reserve(data_->used+1);
// data_->buf[data_->used++]=c;
// }
// else{
// free();
// StringBuf* tmp=new StringBuf(data_->used+1);
// strncpy(tmp.buf,str.data_->buf,data_->used);
// tmp.buf[data_->used+1]=c;
// tmp.used=data_->used+1;
// data_=tmp;
// }
}
bool String::operator==(const String& str)const{
if(data_->buf==str.data_->buf)
return true;
else if(data_->used==str.data_->used)
return strncmp(data_->buf,str.data_->buf,data_->used)==0?true:false;
else
return false;
}
bool String::operator!=(const String& str)const{
return !(*this==str);
}
bool String::operator>(const String& str)const{
if(data_->buf==str.data_->buf)
return false;
else if(data_->used==str.data_->used)
return strncmp(data_->buf,str.data_->buf,data_->used)>0?true:false;
else{
int n=min(data_->used,str.data_->used);
int cmp=strncmp(data_->buf,str.data_->buf,n);
if(cmp==0)
return data_->used<str.data_->used;
else
return cmp>0;
}
}
bool String::operator>=(const String&str)const{
return *this==str||*this>str;
}
bool String::operator<(const String& str)const{
return !(*this>str);
}
bool String::operator<=(const String& str)const{
return *this==str||*this<str;
}
bool String::operator==(const char *str)const{
size_t n=strlen(str);
if(data_->used==n)
return strncmp(data_->buf,str,data_->used)==0?true:false;
else
return false;
}
bool String::operator!=(const char *str)const{
return !(*this==str);
}
bool String::operator>(const char* str)const{
size_t sz=strlen(str);
if(data_->used==sz)
return strncmp(data_->buf,str,data_->used)>0?true:false;
else{
int n=min(data_->used,sz);
int cmp=strncmp(data_->buf,str,n);
if(cmp==0)
return data_->used<sz;
else
return cmp>0;
}
}
bool String::operator>=(const char* str)const {
return *this==str||*this>str;
}
bool String::operator<(const char* str)const {
return !(*this>str);
}
bool String::operator<=(const char* str)const {
return *this==str||*this<str;
}
char& String::operator[](size_t n){
AboutToModify(data_->len,false);
return data_->buf[n];
}
const char String::operator[](size_t n)const{
return data_->buf[n];
}
String operator+(const String& str1,const String& str2){
if(str1.data_->used==0&&str2.data_->used==0)
return String();
else if(str1.data_->used==0&&str2.data_->used!=0){
return String(str2);
}
else if(str1.data_->used!=0&&str2.data_->used==0){
return String(str1);
}
else{
String newstr;
newstr.AboutToModify(str1.data_->used+str1.data_->used,false);
strncpy(newstr.data_->buf,str1.data_->buf,str1.data_->used);
strncpy(newstr.data_->buf+str1.data_->used,str2.data_->buf,str2.data_->used);
newstr.data_->used=str1.data_->used+str2.data_->used;
return newstr;
}
}
String operator+(const String&str1,const char*str2) {
size_t len=strlen(str2);
if(str1.data_->used==0&&len==0)
return String();
else if(str1.data_->used==0&&len!=0){
return String(str2);
}
else if(str1.data_->used!=0&&len==0){
return String(str1);
}
else{
String newstr;
newstr.AboutToModify(str1.data_->used+len,false);
strncpy(newstr.data_->buf,str1.data_->buf,str1.data_->used);
strncpy(newstr.data_->buf+str1.data_->used,str2,len);
newstr.data_->used=str1.data_->used+len;
return newstr;
}
}
istream& operator>>(istream& is,String& str){
const int limit_string_used=4096;
char inBuf[limit_string_used];
is>>setw(limit_string_used)>>inBuf;
str=inBuf;
return is;
}
ostream& operator<<(ostream& os,const String& str){
for(int i=0;i<str.data_->used;i++)
os<<str.data_->buf[i];
return os;
}
int main1()
{
int aCnt = 0, eCnt = 0, iCnt = 0, oCnt = 0, uCnt = 0,
theCnt = 0, itCnt = 0, wdCnt = 0, notVowel = 0;
// 为了使用 operator==( const char* )
// 我们并不定义 The( "The" )和 It( "It" )
String buf, the( "the" ), it( "it" );
// 调用 operator>>( istream&, String& )
while ( cin >> buf ) {
++wdCnt;
// 调用 operator<<( ostream&, const String& )
cout << buf << ' ';
if ( wdCnt % 12 == 0 )
cout << endl;
// 调用 String::operator==(const String&) and
//
if ( buf == the || buf == "The" )
++theCnt;
if ( buf == it || buf == "It" )
++itCnt;
// 调用 String::size()
for ( int ix = 0; ix < buf.size(); ++ix )
{
// 调用 String::operator[](int)
switch( buf[ ix ] )
{
case 'a': case 'A': ++aCnt;
break;
case 'e': case 'E': ++eCnt;
break;
case 'i': case 'I': ++iCnt;
break;
case 'o': case 'O': ++oCnt;
break;
case 'u': case 'U': ++uCnt;
break;
default: ++notVowel; break;
}
}
}
// 调用 operator<<( ostream&, const String& )
cout << "\n\n"
<<"Words read: " << wdCnt << "\n\n"
<<"the/The: " << theCnt << '\n'
<<"it/It: " << itCnt << "\n\n"
<<"non-vowels read: " << notVowel << "\n\n"
<<"a: " << aCnt << '\n'
<<"e: " << eCnt << '\n'
<<"i: " << iCnt << '\n'
<<"o: " << oCnt << '\n'
<<"u: " << uCnt << endl;
String a="hello";
String b="world";
String c=a+b;
cout<<c<<endl;
return 0;
}
int main(){
String s="abc";
cout<<s.data_->refs<<endl;
String s2="abc";
cout<<s2.data_->refs<<endl;
s+="dd";
String s3=s+s2;
cout<<s3<<endl;
cout<<s3.data_->refs<<endl;
String s4(s3);
cout<<s4<<endl;
cout<<s4.data_->refs<<endl;
cout<<s3.data_->refs<<endl;
s4[1]='x';
cout<<s4<<endl;
cout<<s4.data_->refs<<endl;
cout<<s3.data_->refs<<endl;
String s5(s4);
cout<<s5<<endl;
cout<<s5.data_->refs<<endl;
cout<<s4.data_->refs<<endl;
cout<<s3<<endl;
cout<<s3.data_->refs<<endl;
}