#include<iostream>
using namespace std;
class String;
ostream& operator<<(ostream &out, const String&s);
//引用计数器类
class String_rep
{
friend class String;
friend ostream& operator<<(ostream &out, const String&s);
public:
String_rep(const char *str )
:use_count(0)
{
if (str == NULL)
{
data = new char[1];
data[0] = '\0';
}
else
{
data = new char[strlen(str) + 1];
strcpy(data, str);
}
}
String_rep(const String_rep &rep) :use_count(0)
{
data = new char[strlen(rep.data) + 1];
strcpy(data, rep.data);
}
String_rep& operator=(const String_rep &rep)
{
if (this != &rep)
{
delete[]data;
data = new char[strlen(rep.data) + 1];
strcpy(data, rep.data);
}
return *this;
}
~String_rep()
{
delete[]data;
data = NULL;
}
public:
void increase()
{
++use_count;
}
void decrease()
{
if (use_count == 0)
{
delete this; //自杀行为 释放this所指的空间,在释放之前调动这个类的析构函数
}
}
private:
char *data;
int use_count;
};
////////////////////////////////////////////////////////////////////////////////////////
class String
{
friend ostream& operator<<(ostream &out, const String&s);
public:
String(const char* str = " ")
{
rep = new String_rep(str);
rep->increase();
}
String(const String &s)
{
rep = s.rep; //浅拷贝
rep->increase();
}
String& operator=(const String &s)
{
if (this != &s)
{
rep->decrease(); //模拟delete
rep = s.rep; //模拟new
rep->increase(); //模拟strcpy
/*rep = s.rep; //这会更改引用计数器指针 ,造成s内存泄漏
rep->increase();*/
}
return *this;
}
~String()
{
rep->decrease();
}
public:
void to_upper()
{
if (rep->use_count > 1)
{
String_rep* new_rep = new String_rep(rep->data);
rep->decrease();
rep = new_rep;
rep->increase();
}
char* ch = rep->data;
while (*ch != '\0')
{
*ch -= 32;
++ch;
}
}
private:
String_rep *rep; //引用计数器
};
ostream& operator<<(ostream &out, const String&s)
{
out << s.rep->data;
return out;
}
void main()
{
String s1("hello");
String s2(s1);
String s3;
s3 = s2;
cout << "s1=" << s1 << endl;
cout << "s2=" << s2 << endl;
cout << "s3=" << s3 << endl;
s2.to_upper();
cout << "-----------------------------------------------" << endl;
cout << "s1=" << s1 << endl;
cout << "s2=" << s2 << endl;
cout << "s3=" << s3 << endl;
}