一、简介
- 采用了
COW写时复制
的方式实现,即在每个String类数据域之前用了4个字节的空间进行引用计数
。通过拷贝构造函数或者赋值运算符函数进行赋值时不会重新开辟空间,只会对引用计数加一,当有修改操作时,才会重新开辟新的空间; - 内部定义了一个char类型的
内部代理类
,用于解决String类重载下标运算符后无法区分读写操作的问题。
二、头文件
#pragma once
#include <iostream>
class String {
class CharProxy {
public:
CharProxy(int index, String &str);
char &operator=(const char &c);
friend std::ostream &operator<<(std::ostream &os, const CharProxy &charPorxy);
private:
int _index;
String &_this;
};
public:
String();
String(const char *pstr);
String(const String &str);
~String();
String &operator=(const String &str);
String &operator=(const char *pstr);
String &operator+=(const String &str);
String &operator+=(const char *pstr);
String::CharProxy operator[](std::size_t index);
std::size_t size()const;
const char* c_str()const;
friend bool operator==(const String &leftStr, const String &rightStr);
friend bool operator!=(const String &leftStr, const String &rightStr);
friend bool operator<(const String &leftStr, const String &rightStr);
friend bool operator>(const String &leftStr, const String &rightStr);
friend bool operator<=(const String &leftStr, const String &rightStr);
friend bool operator>=(const String &leftStr, const String &rightStr);
friend std::ostream &operator<<(std::ostream &os, const String &str);
friend std::istream &operator>>(std::istream &is, String &str);
int refCount();
friend std::ostream &operator<<(std::ostream &os, const CharProxy &charPorxy);
private:
char *malloc(const char *pstr = nullptr);
void release();
void initRefCount();
void increaseRefCount();
void decreaseRefCount();
static const int refCountLength = 4;
char * _pstr;
};
String operator+(const String &thisStr, const String &otherStr);
String operator+(const String &thisStr, const char *otherpStr);
String operator+(const char *thisPstr, const String &otherStr);
三、String实现
#include <cstring>
#include "08_MyString.hh"
using namespace std;
String::CharProxy::CharProxy(int index, String &str) :_index(index), _this(str) {
cout << "CharProxy()" << endl;
}
char &String::CharProxy::operator=(const char &c) {
cout << "char &operator=(const char &c)" << endl;
if (_index < strlen(_this._pstr)) {
if (*(int*)(_this._pstr - refCountLength) > 1) {
_this.decreaseRefCount();
char *newStr = _this.malloc(_this._pstr);
strcpy(newStr, _this._pstr);
_this._pstr = newStr;
_this.initRefCount();
}
_this._pstr[_index] = c;
return _this._pstr[_index];
}else {
static char nullchar = '\0';
return nullchar;
}
}
ostream &operator<<(std::ostream &os, const String::CharProxy &charPorxy) {
if (charPorxy._index < strlen(charPorxy._this._pstr)) {
os << charPorxy._this._pstr[charPorxy._index];
}else {
os << "out of range";
}
return os;
}
char *String::malloc(const char *pstr) {
if (pstr == nullptr) {
return new char[1 + refCountLength]() + refCountLength;
} else {
return new char[strlen(pstr) + 1 + refCountLength]() + refCountLength;
}
}
void String::release() {
decreaseRefCount();
if (refCount() == 0) {
delete [] (_pstr - refCountLength);
_pstr = nullptr;
cout << "release()......." << endl;
}
}
void String::initRefCount() {
*(int*)(_pstr - refCountLength) = 1;
}
void String::increaseRefCount(){
++*(int*)(_pstr - refCountLength);
}
void String::decreaseRefCount(){
--*(int*)(_pstr - refCountLength);
}
int String::refCount() {
return *(int*)(_pstr - refCountLength);
}
String::String()
: _pstr(malloc())
{
initRefCount();
strcpy(_pstr, "");
cout << "String()" << endl;
}
String::String(const char *pstr)
: _pstr(malloc(pstr))
{
initRefCount();
strcpy(_pstr, pstr);
cout << "String(const char *pstr) " << endl;
}
String::String(const String &str)
: _pstr(str._pstr)
{
increaseRefCount();
cout << "String(const String &str)" << endl;
}
String::~String() {
release();
}
String &String::operator=(const String &str) {
if (this != &str && strcmp(_pstr, str._pstr) != 0) {
release();
_pstr = str._pstr;
increaseRefCount();
}
return *this;
}
String &String::operator=(const char *pstr) {
if (strcmp(_pstr, pstr) != 0) {
release();
_pstr = malloc(pstr);
initRefCount();
strcpy(_pstr, pstr);
}
return *this;
}
String &String::operator+= (const String &str) {
if (str._pstr != nullptr && strlen(str._pstr) > 0) {
size_t newLen = strlen(_pstr) + strlen(str._pstr) + refCountLength + 1;
char *newStr = new char[newLen]() + refCountLength;
strcat(newStr, _pstr);
strcat(newStr, str._pstr);
release();
_pstr = newStr;
initRefCount();
}
return *this;
}
String &String::operator+= (const char *pstr) {
if (pstr != nullptr && strlen(pstr) > 0) {
size_t newLen = strlen(_pstr) + strlen(pstr) + refCountLength + 1;
char *newStr = new char[newLen]() + refCountLength;
strcat(newStr, _pstr);
strcat(newStr, pstr);
release();
_pstr = newStr;
initRefCount();
}
return *this;
}
String::CharProxy String::operator[] (size_t index) {
return String::CharProxy(index, *this);
}
size_t String::size() const {
return strlen(_pstr);
}
const char *String::c_str() const {
return _pstr;
}
bool operator==(const String &leftStr, const String &rightStr) {
return strcmp(leftStr._pstr, rightStr._pstr) == 0 ? true : false;
}
bool operator!=(const String &leftStr, const String &rightStr) {
return strcmp(leftStr._pstr, rightStr._pstr) != 0 ? true : false;
}
bool operator<(const String &leftStr, const String &rightStr) {
return strcmp(leftStr._pstr, rightStr._pstr) < 0 ? true : false;
}
bool operator>(const String &leftStr, const String &rightStr) {
return strcmp(leftStr._pstr, rightStr._pstr) > 0 ? true : false;
}
bool operator<=(const String &leftStr, const String &rightStr) {
int res = strcmp(leftStr._pstr, rightStr._pstr);
return res > 0 ? false : true;
}
bool operator>=(const String &leftStr, const String &rightStr) {
int res = strcmp(leftStr._pstr, rightStr._pstr);
return res < 0 ? false : true;
}
ostream &operator<< (ostream &os, const String &str) {
os << str._pstr;
return os;
}
istream &operator>> (istream &is, String &str) {
if (strlen(str._pstr) > 0) {
str = "";
}
char buf[1024];
while (1) {
is.clear();
bzero(buf, sizeof(buf));
is.get(buf, sizeof(buf));
int len = strlen(buf);
if (len == 0) {
break;
}
str += buf;
}
return is;
}
String operator+(const String &thisStr, const String &otherStr) {
if (strlen(thisStr.c_str()) == 0) {
return otherStr;
}
if (strlen(otherStr.c_str()) == 0) {
return thisStr;
}
String temp(thisStr);
temp+=otherStr;
return temp;
}
String operator+(const String &thisStr, const char *otherPstr) {
if (strlen(thisStr.c_str()) == 0) {
return String(otherPstr);
}
if (strlen(otherPstr) == 0) {
return thisStr;
}
String temp(thisStr);
temp+=otherPstr;
return temp;
}
String operator+(const char *thisPstr, const String &otherStr) {
if (strlen(thisPstr) == 0) {
return otherStr;
}
if (strlen(otherStr.c_str()) == 0) {
return String(thisPstr);
}
String temp(thisPstr);
temp+=otherStr;
return temp;
}