【String】引用计数实现String

String.h

#ifndef STRING_H
#define STRING_H
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
//String
class String{
public:
	String(const char* str = NULL);//constructor
	String(const String& rhs);//copy constructor
	String& operator=(const String& rhs);//copy assignment
	~String();//destructor
	
	String& operator+=(const String& rhs);//operator+=
	String operator+(const String& rhs);//operator+
	bool operator==(const String& rhs);//operator==
	char& operator[](size_t index); //operator[]
	const char& operator[](size_t index)const;//const operator[]
	
	void copy(const String& rhs);//copy
	int compare(const String& rhs);//compare
	String substr(size_t pos, size_t len);//substring
	String& insert(size_t pos, String& rhs);//insert
	String& erase(size_t pos, size_t len);//erase
	bool empty();//whether String is empty or not
	size_t length();//get String length

	size_t get_ref_count();//get ref_count
	friend std::istream& operator>>(std::istream& is, const String& str);//operator>>
	friend std::ostream& operator<<(std::ostream& os, const String& str);//operator<<
private:
	struct StringValue{
		int ref_count;
		char* data;
		StringValue(const char* str);//StringValue constructor
		~StringValue();//StringValue destructor
	};
	StringValue* value;
};
//StringValue constructor
String::StringValue::StringValue(const char* str) :ref_count(1){
	if (str == NULL){
		data = new char[1];
		data[0] = '\0';
	}
	else{
		data = new char[strlen(str) + 1];
		strcpy(data, str);
	}
}
//StringValue destructor
String::StringValue::~StringValue(){
	delete[] data;
	data = NULL;
}
//constructor
String::String(const char* str) :value(new StringValue(str)){}
//copy constructor
String::String(const String& rhs):value(rhs.value){
	++value->ref_count;
}
//copy assignment
String& String::operator=(const String& rhs){
	if (this->value == rhs.value)
		return *this;

	if (--this->value->ref_count == 0)
		delete this->value;

	this->value = rhs.value;
	++this->value->ref_count;
	return *this;
}
//destructor
String::~String(){
	if (--this->value->ref_count == 0)
		delete this->value;
}
//operator+=
String& String::operator+=(const String& rhs){
	if (--this->value->ref_count == 0)
		delete this->value;
	if (rhs.value->data == NULL){
		this->value = new StringValue(this->value->data);
		return *this;
	}
	if (this->value->data == NULL){
		this->value = new StringValue(rhs.value->data);
		return *this;
	}
	char* temp = new char[strlen(this->value->data) + strlen(rhs.value->data) + 1];
	strcpy(temp, this->value->data);
	strcat(temp, rhs.value->data);
	this->value = new StringValue(temp);
	return *this;
}
//operator+
String String::operator+(const String& rhs){
	return String(*this) += rhs;
}
//operator==
bool String::operator==(const String& rhs){
	return compare(rhs) == 0 ? true : false;
}
//operator[]
char& String::operator[](size_t index){
	if (this->value->ref_count > 1){
		--this->value->ref_count;
		this->value = new StringValue(this->value->data);
	}
	if (index < strlen(this->value->data))
		return this->value->data[index];
}
//const operator[]
const char& String::operator[](size_t index)const{
	if (index < strlen(this->value->data))
		return this->value->data[index];
}
//copy
void String::copy(const String& rhs){
	operator=(rhs);
}
//compare
int String::compare(const String& rhs){
	for (int i = 0; i < strlen(this->value->data) && i < strlen(rhs.value->data); i++){
		if (this->value->data[i] != rhs.value->data[i]){
			return this->value->data[i] - rhs.value->data[i];
		}
	}
	return strlen(this->value->data) - strlen(rhs.value->data);
}
//substring
String String::substr(size_t pos, size_t len){
	if (pos>length()-len){
		std::cout << "pos+len>String length" << std::endl;
		exit(1);
	}
	char* temp = new char[len + 1];
	int i;
	for (i = 0; i < len; i++){
		temp[i] = this->value->data[pos + i];
	}
	temp[i] = '\0';
	return String(temp);
}
//insert
String& String::insert(size_t pos, String& rhs){
	if (pos>this->length()){
		std::cout << "pos>String length" << std::endl;
		exit(1);
	}
	if (--this->value->ref_count == 0)
		delete this->value;
	char* temp = new char[this->length() + rhs.length() + 1];
	int i;
	for (i = 0; i < pos; i++){
		temp[i] = this->value->data[i];
	}
	for (; i < pos + rhs.length(); i++){
		temp[i] = rhs.value->data[i - pos];
	}
	for (; i < this->length() + rhs.length(); i++){
		temp[i] = this->value->data[i - rhs.length()];
	}
	temp[i] = '\0';
	this->value = new StringValue(temp);
	return *this;
}
//erase
String& String::erase(size_t pos, size_t len){
	if (pos>this->length()-len){
		std::cout << "pos+len>String length" << std::endl;
		exit(1);
	}
	if (--this->value->ref_count == 0)
		delete this->value;
	char* temp = new char[this->length() - len + 1];
	int i;
	for (i = 0; i < pos; i++){
		temp[i] = this->value->data[i];
	}
	for (; i < this->length() - len + 1; i++){
		temp[i] = this->value->data[i + len];
	}
	temp[i] = '\0';
	this->value = new StringValue(temp);
	return *this;
}
//whether String is empty or not
bool String::empty(){
	return this->value->data[0] == '\0' ? true : false;
}
//get String length
size_t String::length(){
	return strlen(this->value->data);
}
//get ref_count
size_t String::get_ref_count(){
	return this->value->ref_count;
}
//operator>>
std::istream& operator>>(std::istream& is, const String& str){
	is >> str.value->data;
	return is;
}
//operator<<
std::ostream& operator<<(std::ostream& os, const String& str){
	os << str.value->data;
	return os;
}

#endif
main.cpp

#include"String.h"  
using namespace std;

int main(){
	String str1("hello world");//call constructor
	String str2 = str1;//call copy constructor
	String str3;//call constructor
	cout << boolalpha << str1.empty() << endl;//false
	cout << boolalpha << str2.empty() << endl;//false
	cout << boolalpha << str3.empty() << endl;//true
	str3 = str2;//call copy assignment
	cout << "str1 reference count:" << str1.get_ref_count() << endl; // 3  
	cout << "str2 reference count:" << str2.get_ref_count() << endl; // 3  
	cout << "str3 reference count:" << str3.get_ref_count() << endl; // 3  

	str1[0] = 'H';//call operator[]
	cout << str1 << endl; //"Hello world"  
	cout << str2 << endl;//"hello world"  
	cout << str3 << endl;//"hello world"   
	cout << "str1 reference count:" << str1.get_ref_count() << endl;//1  
	cout << "str2 reference count:" << str2.get_ref_count() << endl;//2  
	cout << "str3 reference count:" << str3.get_ref_count() << endl;//2  

	String str4("hello");//call constructor
	String str5 = str4;//call copy constructor 
	String str6 = " world";//call constructor 

	str5 = str5 + str6;//call operator+,copy constructor
	cout << str4 << endl; //"hello"  
	cout << str5 << endl; //"hello world"  
	cout << str6 << endl; //" world"  
	cout << "str4 reference count:" << str4.get_ref_count() << endl;//1  
	cout << "str5 reference count:" << str5.get_ref_count() << endl;//1  
	cout << "str6 reference count:" << str6.get_ref_count() << endl;//1  

	String str7 = str5;//call copy constructor 
	String str8;//call constructor
	str8 = str7;////call copy constructor 
	cout << str7 << endl; //"hello world"  
	cout << "str5 reference count:" << str5.get_ref_count() << endl;//3  
	cout << "str7 reference count:" << str7.get_ref_count() << endl;//3  
	cout << "str8 reference count:" << str8.get_ref_count() << endl;//3  

	str5 += str6;//call operator+=
	cout << str5 << endl; //"hello world world"  
	cout << str6 << endl; //" world"  
	cout << str7 << endl; //"hello world"  
	cout << str8 << endl; //"hello world"  
	cout << "str5 reference count:" << str5.get_ref_count() << endl; //1  
	cout << "str6 reference count:" << str6.get_ref_count() << endl;//1  
	cout << "str7 reference count:" << str7.get_ref_count() << endl;//2  
	cout << "str8 reference count:" << str8.get_ref_count() << endl;//2  

	String str9; //call constructor
	str9 = str8.substr(1, 3);
	cout << str9 << endl;//"ell"
	cout << "str8 reference count:" << str8.get_ref_count() << endl;//2  
	cout << "str9 reference count:" << str9.get_ref_count() << endl;//1  
	cout << "str9 length:" << str9.length() << endl;//3

	String str10;
	str10.copy(str9);
	cout << str9 << endl;//"ell"
	cout << str10 << endl;//"ell"
	cout << "str9 reference count:" << str9.get_ref_count() << endl;//2  
	cout << "str10 reference count:" << str10.get_ref_count() << endl;//2

	if (str9.compare(str10) == 0)
		cout << "equal" << endl; //equal
	else
		cout << " not equal" << endl;

	str10.insert(2, String("abc"));
	cout << str9 << endl;//"ell"
	cout << str10 << endl;//"elabcl"
	cout << "str9 reference count:" << str9.get_ref_count() << endl;//1  
	cout << "str10 reference count:" << str10.get_ref_count() << endl;//1

	String str11 = str10;
	cout << str10 << endl;//"elabcl"
	cout << str11 << endl;//"elabcl"
	cout << "str10 reference count:" << str10.get_ref_count() << endl;//2 
	cout << "str11 reference count:" << str11.get_ref_count() << endl;//2

	str11.erase(2, 2);
	cout << str10 << endl;//"elabcl"
	cout << str11 << endl;//"elcl"
	cout << "str10 reference count:" << str10.get_ref_count() << endl;//1  
	cout << "str11 reference count:" << str11.get_ref_count() << endl;//1

	return 0;
}

你可能感兴趣的:(【String】引用计数实现String)