PIMPL实现String(pointer to implementation)

本文介绍了一种基于C++的字符串池化技术实现方法,通过Copy-On-Write(写时复制)机制来提高字符串操作的效率并减少内存消耗。文章详细解释了字符串类的设计,包括构造函数、析构函数、赋值运算符等,并展示了如何利用这些机制来避免不必要的字符串复制。




#include <iostream>
#include <string.h>
using namespace std;

class String;

class StringRep {
friend class String;
friend ostream& operator<<(ostream& os, const String& s);
	StringRep(const char* s);  // StringRep constructor
	~StringRep();  // StringRep destructor
	int count;
	char *rep;
};

// StringRep constructor
StringRep::StringRep(const char* s):count(1) {
	if(NULL == s) {
		rep = new char[1];
		*rep= '\0';
	}
	else {
		rep = new char[strlen(s)+1];
		strcpy(rep, s);		
	}
}

// StringRep destructor
StringRep::~StringRep() {
	delete[] rep;
	rep = NULL;
}

class String {
public:
	String();  // default constructor
	String(const char* s);  // constructor
	String(const String& s); // copy constructor
	String& operator=(const String& s);  // copy assignment
	~String();  // destructor
public:
	bool empty() {
		return this->rep->rep[0] == '\0'? true:false;
	}
	int length() {
		return strlen(this->rep->rep);
	}
	int get_rep_count() {
		return this->rep->count;
	}

public:
	//Copy-On-Write
	String& operator+=(const String& s);  // operator+=	
	String operator+(const String& s);  // operator+
	char& operator[](size_t index); // operator[]
	const char& operator[](size_t index)const ; // const operator[]


public:
	friend ostream& operator<<(ostream &os, const String& s);  // operator<<
private:
	StringRep* rep;  // pimpl 
};

// default constructor
String::String():rep(new StringRep(NULL)) {
}

// constructor
String::String(const char* s):rep(new StringRep(s)) {
}

// copy constructor
String::String(const String& s):rep(s.rep) {
	//1.地址赋值2.引用计数++
	++rep->count;
}


// copy assignment
String& String::operator=(const String& s) {
	//1.判断是否为同一个字符串地址
	if(this->rep == s.rep) {
		return *this;
	}
	//2.原始引用地址的引用计数--
	if(0 == --this->rep->count) {
		delete this->rep;
	}
 	//3.更新地址	
	this->rep = s.rep;
	//4.新地址?引用计数++
	++this->rep->count;
	return *this;
}

// destructor 
String::~String() {
	//引用计数减为0的时候,才会销毁原始地址
	if(0 == --this->rep->count) {
		delete this->rep;
	}
}


// operator<<
ostream& operator<<(ostream &os, const String& s) {
	os << s.rep->rep ;
	return os;
}

//Copy-On-Write
//operator+=
String& String::operator+=(const String& s) {
	//1.原始地址引用计数--,清空地址
	if(0 == --this->rep->count) {
		//注意这种情况:  str+=str;
		if(this != &s) {
		//if(this->rep != s.rep) {
			delete this->rep;
		}
	}
	//2.s.rep->rep 为空
	if(NULL == s.rep->rep) {
		this->rep = new StringRep(this->rep->rep);
		return *this;
	}
	//3.this->rep->rep 为空
	if(NULL == this->rep->rep) {
		this->rep = new StringRep(s.rep->rep);
		return *this;	
	}
	//4.申请空间构造字符
	char *temp = new char[strlen(this->rep->rep)+ strlen(s.rep->rep)+1];
	strcpy(temp, this->rep->rep);
	strcat(temp, s.rep->rep);
	
	//上面str+=str;这种情况处理完成,如果此时引用计数为0,则销毁,防止内存泄漏
	//if(0 == this->rep->count && this->rep == s.rep) {	
	if(0 == this->rep->count && this == &s) {	
		delete this->rep;
	}
	//5.为委托指针赋值
	this->rep = new StringRep(temp);
	//6.删除申请空间
	delete []temp;
	temp = NULL;	
	//7.返回新对象
	return *this;
		
}



//Copy-On-Write
String String::operator+(const String& s)  // operator+
{
	return String(*this) += s;
}


//Copy-On-Write
char& String::operator[](size_t index) // operator[]
{
	//如果引用数目>1,拷贝一份
	if(this->rep->count > 1) {
		--this->rep->count;
		this->rep = new StringRep(this->rep->rep);
	}
	//否则现在就是1份,直接使用即可
	if(index < length()) {
		return this->rep->rep[index];
	} 
}


const char& String::operator[](size_t index) const  // const operator[]
{
	if(index < strlen(this->rep->rep)) {
		return this->rep->rep[index];
	}
}




int main() {
	String str1 = "hello";
	cout << "str1: " << str1 << " str1:count " << str1.get_rep_count() << endl;
	cout << "------------------------------" << endl;
	String str2 = str1;
	cout << "str1: " << str1 << " str1:count " << str1.get_rep_count() << endl;
	cout << "str2: " << str2 << " str2:count " << str2.get_rep_count() << endl;
	cout << "------------------------------" << endl;
	str2 = "hello";
	//str2不引用str1的rep,所以count会--
	cout << "str1: " << str1 << " str1:count " << str1.get_rep_count() << endl;
	cout << "str2: " << str2 << " str2:count " << str2.get_rep_count() << endl;
	cout << "------------------------------" << endl;
	
	String str3=str2;
	String str4=str2;
	//str1是原始位置,str3,str4都是引用str2位置
	cout << "str1: " << str1 << " str1:count " << str1.get_rep_count() << endl;
	cout << "str2: " << str2 << " str2:count " << str2.get_rep_count() << endl;
	cout << "str3: " << str3 << " str3:count " << str3.get_rep_count() << endl;
	cout << "str4: " << str4 << " str4:count " << str4.get_rep_count() << endl;
	cout << "------------------------------" << endl;


	
	/*str2 += str2;
	//str2不在使用原来位置,引用计数--,str4,str3
	cout << "str1: " << str1 << " str1:count " << str1.get_rep_count() << endl;
	cout << "str2: " << str2 << " str2:count " << str2.get_rep_count() << endl;
	cout << "str3: " << str3 << " str3:count " << str3.get_rep_count() << endl;
	cout << "str4: " << str4 << " str4:count " << str4.get_rep_count() << endl;
	cout << "------------------------------" << endl;*/
	
	str2 += str3;
	cout << "str1: " << str1 << " str1:count " << str1.get_rep_count() << endl;
	cout << "str2: " << str2 << " str2:count " << str2.get_rep_count() << endl;
	cout << "str3: " << str3 << " str3:count " << str3.get_rep_count() << endl;
	cout << "str4: " << str4 << " str4:count " << str4.get_rep_count() << endl;
	cout << "------------------------------" << endl;
	
		
	str4=str2;
	
	String str5;
	String temp("++++");
	cout << "str5: " << str5<< " str5:count " << str5.get_rep_count() << endl;
	str5 = str2 + temp;
	cout << "str1: " << str1 << " str1:count " << str1.get_rep_count() << endl;
	cout << "str2: " << str2 << " str2:count " << str2.get_rep_count() << endl;
	cout << "str3: " << str3 << " str3:count " << str3.get_rep_count() << endl;
	cout << "str4: " << str4 << " str4:count " << str4.get_rep_count() << endl;
	cout << "str5: " << str5<< " str5:count " << str5.get_rep_count() << endl;
	cout << "------------------------------" << endl;
        	
	char ch = str2[3];
	cout << "index_char[3]: " << ch << endl;
	cout << "str1: " << str1 << " str1:count " << str1.get_rep_count() << endl;
	cout << "str2: " << str2 << " str2:count " << str2.get_rep_count() << endl;
	cout << "str3: " << str3 << " str3:count " << str3.get_rep_count() << endl;
	cout << "str4: " << str4 << " str4:count " << str4.get_rep_count() << endl;
	cout << "str5: " << str5<< " str5:count " << str5.get_rep_count() << endl;
	cout << "------------------------------" << endl;
	
	const char ch2 = str2[4];
	cout << "index_char[2]: " << ch2 << endl;
	cout << "str1: " << str1 << " str1:count " << str1.get_rep_count() << endl;
	cout << "str2: " << str2 << " str2:count " << str2.get_rep_count() << endl;
	cout << "str3: " << str3 << " str3:count " << str3.get_rep_count() << endl;
	cout << "str4: " << str4 << " str4:count " << str4.get_rep_count() << endl;
	cout << "str5: " << str5<< " str5:count " << str5.get_rep_count() << endl;
	cout << "------------------------------" << endl;
	

	return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值