一、简介
- 采用了
COW写时复制
的方式实现,即在每个String类数据域之前用了4个字节的空间进行引用计数
。通过拷贝构造函数或者赋值运算符函数进行赋值时不会重新开辟空间,只会对引用计数加一,当有修改操作时,才会重新开辟新的空间; - 内部定义了一个char类型的
内部代理类
,用于解决String类重载下标运算符后无法区分读写操作的问题。
二、头文件
#pragma once
#include <iostream>
class String {
class CharProxy { // char类型的代理内部类
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; // 返回一个C风格的字符串
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) { // 判断引用计数是否大于1
_this.decreaseRefCount(); // 原空间引用计数-1
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);
}
/**
* 返回C风格字符串
*/
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 = ""; // str非空就先清空str
}
char buf[1024];
while (1) {
is.clear(); // 恢复流的状态
bzero(buf, sizeof(buf)); // 清空buf
is.get(buf, sizeof(buf)); // 读取一个buf的大小
int len = strlen(buf);
if (len == 0) { // buf长度为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;
}
本文含有隐藏内容,请 开通VIP 后查看