短字符串优化(SSO)
实现1
实现2
写时复制
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstring>
using std::cout;
using std::endl;// 引用计数存放的位置
// 1. 存放在栈上 --- 不行
// 2. 存放在全局静态区 --- 不行
// 3. 只能放在堆上
class String
{
public:String();String(const char* pstr);String(const String& rhs);String& operator=(const String& rhs);~String();const char* c_str() const;int getRefCount()const;friend std::ostream& operator<<(std::ostream& os, const String& rhs);char& operator[](size_t index);
private:size_t size()const;
private:char* _pstr;
};
String::String() :_pstr(new char[5] + 4)
{// 5: 引用计数+‘\0’ 4:让其直接指向数据的位置//cout << "String()" << endl;*(int*)(_pstr - 4) = 1;
}
String::String(const char* pstr):_pstr(new char[strlen(pstr) + 5]()+4)/*_pstr(new char(strlen(pstr)+1))*/
{//cout << "String::String(const char* pstr)" << endl;strcpy(_pstr,pstr);(*(int*)(_pstr - 4)) = 1;
}
// String s2(s1)
String::String(const String& rhs):_pstr(rhs._pstr) // 浅拷贝
{//cout << "String::String(const String& rhs)" << endl;(*(int*)(_pstr - 4))++;
}
String& String::operator=(const String& rhs)
{if (&rhs != this) //1. 自赋值{// 2. 释放左操作(*(int*)(_pstr - 4))--;if (0 == (*(int*)(_pstr - 4))){delete[](_pstr - 4);}// 3. 深拷贝(浅拷贝)_pstr = rhs._pstr;(*(int*)(_pstr - 4))++;}return *this;
}
String::~String()
{cout << "~String()" << endl;(*(int*)(_pstr - 4))--;if (0 == (*(int*)(_pstr - 4))){delete[](_pstr - 4);}
}
const char* String::c_str() const
{return _pstr;
}
int String::getRefCount() const
{return *(int*)(_pstr - 4);
}
std::ostream& operator<<(std::ostream& os, const String& rhs)
{if (rhs._pstr != NULL) {os << rhs._pstr << endl;}return os;
}
size_t String::size()const
{return strlen(_pstr);
}
char& String::operator[](size_t index)
{if (index > size()) {static char charnull = '\0';return charnull;}else {if (getRefCount() > 1) { // 考虑是不是共享的// 执行深拷贝int len = size();char* tmp = new char[len+5]()+4;strcpy(tmp,_pstr);(*(int*)(_pstr - 4))--; // 注意这里不需要看是否等于0,因为getRefCount() > 1_pstr = tmp;(*(int*)(_pstr - 4)) = 1;/*return _pstr[index];*/ // 这个要写到括号之外,可能这个字符串没有被共享}return _pstr[index];}
}//std::ostream& operator<<(std::ostream& os, char ch)
//{
// os << "std::ostream& operator<<(std::ostream& os, char ch)" << endl;
// os << ch;
// return os;
//}
int main(void)
{String s1("hello");String s2(s1);cout << "s1 = " << s1 << endl;cout << "s2 = " << s2 << endl;cout << "s2 RefCount= " << s2.getRefCount() << endl;cout << "s2 RefCount= " << s2.getRefCount() << endl;printf("s1`address = %p\n",s1.c_str());printf("s2`address = %p\n",s2.c_str());String s3("world");cout << "s3 = " << s3 << endl;cout << "s3 RefCount= " << s3.getRefCount() << endl;cout << endl << "使用s3对s1进行赋值操作" << endl;s3 = s1;cout << "s1 = " << s1 << endl;cout << "s2 = " << s2 << endl;cout << "s3 = " << s3 << endl;cout << "s1 RefCount= " << s1.getRefCount() << endl;cout << "s2 RefCount= " << s2.getRefCount() << endl;cout << "s3 RefCount= " << s3.getRefCount() << endl;printf("s1`address = %p\n", s1.c_str());printf("s2`address = %p\n", s2.c_str());printf("s3`address = %p\n", s3.c_str());cout << endl << endl << "对s3[0]执行写操作" << endl;s3[0] = 'H';cout << "s1 = " << s1 << endl;cout << "s2 = " << s2 << endl;cout << "s3 = " << s3 << endl;cout << "s1 RefCount= " << s1.getRefCount() << endl;cout << "s2 RefCount= " << s2.getRefCount() << endl;cout << "s3 RefCount= " << s3.getRefCount() << endl;printf("s1`address = %p\n", s1.c_str());printf("s2`address = %p\n", s2.c_str());printf("s3`address = %p\n", s3.c_str());/*如何区分是对[] 读还是写cout<<s[1] 是进行的读操作; 可以对[]进行重载s[1] = '1' 是进行的写操作; 可以对=进行重载*/// 读操作//cout << s1[1] << endl;return 0;
}
-
如何区分什么什么时候读,什么时候写
- 通过一个中间类型CharProxy,并且重载他的operator=和operator<<函数
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstring>
using std::cout;
using std::endl;// 引用计数存放的位置
// 1. 存放在栈上 --- 不行
// 2. 存放在全局静态区 --- 不行
// 3. 只能放在堆上
class String
{
public:String();String(const char* pstr);String(const String& rhs);String& operator=(const String& rhs);~String();const char* c_str() const;int getRefCount()const;friend std::ostream& operator<<(std::ostream& os, const String& rhs);
private:class CharProxy {public:CharProxy( String& self, size_t idx) :_self(self), _idx(idx) {}char& operator = (const char& ch); // 写操作/*{_self[_idx] = ch;return _self[_idx];}*/friend std::ostream& operator<<(std::ostream& os, const CharProxy& ch);private:String &_self; // 此时String是不完整类型size_t _idx;};
public:friend std::ostream& operator<<(std::ostream& os, const CharProxy& ch);//char& operator[](size_t index);CharProxy operator[](size_t idx){return CharProxy(*this,idx);}
private:void initRefCount();void increaseRefCount();void decreaseRefCount();void release();size_t size()const;
private:char* _pstr;
};
String::String() :_pstr(new char[5] + 4)
{// 5: 引用计数+‘\0’ 4:让其直接指向数据的位置//cout << "String()" << endl;initRefCount();
}
String::String(const char* pstr):_pstr(new char[strlen(pstr) + 5]()+4)/*_pstr(new char(strlen(pstr)+1))*/
{//cout << "String::String(const char* pstr)" << endl;strcpy(_pstr,pstr);//(*(int*)(_pstr - 4))--;initRefCount();
}
// String s2(s1)
String::String(const String& rhs):_pstr(rhs._pstr) // 浅拷贝
{//cout << "String::String(const String& rhs)" << endl;//(*(int*)(_pstr - 4))++;increaseRefCount();
}
String& String::operator=(const String& rhs)
{if (&rhs != this) //1. 自赋值{// 2. 释放左操作//(*(int*)(_pstr - 4))--;/*decreaseRefCount();if (0 == (*(int*)(_pstr - 4))){delete[](_pstr - 4);}*/release();// 3. 深拷贝(浅拷贝)_pstr = rhs._pstr;//(*(int*)(_pstr - 4))++;increaseRefCount();}return *this;
}
String::~String()
{//cout << "~String()" << endl;//(*(int*)(_pstr - 4))--;//decreaseRefCount();//if (0 == (*(int*)(_pstr - 4)))//{// delete[](_pstr - 4);//}release();
}
void String::initRefCount()
{*(int*)(_pstr - 4) = 1;
}
void String::increaseRefCount()
{(*(int*)(_pstr - 4))++;
}
void String::decreaseRefCount()
{(*(int*)(_pstr - 4))--;
}
void String::release()
{ decreaseRefCount();if (0 == (*(int*)(_pstr - 4))){delete[](_pstr - 4);}
}
const char* String::c_str() const
{return _pstr;
}
int String::getRefCount() const
{return *(int*)(_pstr - 4);
}
std::ostream& operator<<(std::ostream& os, const String& rhs)
{if (rhs._pstr != NULL) {os << rhs._pstr << endl;}return os;
}
size_t String::size()const
{return strlen(_pstr);
}
char& String::CharProxy::operator = (const char& ch) // 写操作
{if (_idx > _self.size()) {static char charnull = '\0';return charnull;}else {if (_self.getRefCount() > 1) { // 考虑是不是共享的// 执行深拷贝int len = _self.size();char* tmp = new char[len+5]()+4;strcpy(tmp, _self._pstr);//(*(int*)(_pstr - 4))--; // 注意这里不需要看是否等于0,因为getRefCount() > 1_self.decreaseRefCount();_self._pstr = tmp;_self.initRefCount();/*return _pstr[index];*/ // 这个要写到括号之外,可能这个字符串没有被共享}_self._pstr[_idx] = ch;return _self._pstr[_idx];}
}
//双友元的设置
std::ostream& operator<<(std::ostream& os, const String::CharProxy& rhs)
// 注意这个函数既要左CharProxy的友元也要作为String的友元(不然上面的代码const String::CharProxy& ch处会报错)
{os << rhs._self._pstr[rhs._idx];return os;
}
//char& String::operator[](size_t index)
//{
// if (index > size()) {
// static char charnull = '\0';
// return charnull;
// }
// else {
// if (getRefCount() > 1) { // 考虑是不是共享的
// // 执行深拷贝
// int len = size();
// char* tmp = new char[len+5]()+4;
// strcpy(tmp,_pstr);
//
// //(*(int*)(_pstr - 4))--; // 注意这里不需要看是否等于0,因为getRefCount() > 1
// decreaseRefCount();
// _pstr = tmp;
// //(*(int*)(_pstr - 4)) = 1;
// initRefCount();
// /*return _pstr[index];*/ // 这个要写到括号之外,可能这个字符串没有被共享
// }
// return _pstr[index];
// }
//}//std::ostream& operator<<(std::ostream& os, char ch)
//{
// os << "std::ostream& operator<<(std::ostream& os, char ch)" << endl;
// os << ch;
// return os;
//}
int main(void)
{String s1("hello");String s2(s1);cout << "s1 = " << s1 << endl;cout << "s2 = " << s2 << endl;cout << "s2 RefCount= " << s2.getRefCount() << endl;cout << "s2 RefCount= " << s2.getRefCount() << endl;printf("s1`address = %p\n",s1.c_str());printf("s2`address = %p\n",s2.c_str());String s3("world");cout << "s3 = " << s3 << endl;cout << "s3 RefCount= " << s3.getRefCount() << endl;cout << endl << "使用s3对s1进行赋值操作" << endl;s3 = s1;cout << "s1 = " << s1 << endl;cout << "s2 = " << s2 << endl;cout << "s3 = " << s3 << endl;cout << "s1 RefCount= " << s1.getRefCount() << endl;cout << "s2 RefCount= " << s2.getRefCount() << endl;cout << "s3 RefCount= " << s3.getRefCount() << endl;printf("s1`address = %p\n", s1.c_str());printf("s2`address = %p\n", s2.c_str());printf("s3`address = %p\n", s3.c_str());cout << endl << endl << "对s3[0]执行写操作" << endl;s3[0] = 'H';// 首先会调用s1.operator[](1)返回一个CharProxy对象,然后调用CharProxy的operatpr=()函数cout << "s1 = " << s1 << endl;cout << "s2 = " << s2 << endl;cout << "s3 = " << s3 << endl;cout << "s1 RefCount= " << s1.getRefCount() << endl;cout << "s2 RefCount= " << s2.getRefCount() << endl;cout << "s3 RefCount= " << s3.getRefCount() << endl;printf("s1`address = %p\n", s1.c_str());printf("s2`address = %p\n", s2.c_str());printf("s3`address = %p\n", s3.c_str());/*如何区分是对[] 读还是写cout<<s[1] 是进行的读操作; 可以对[]进行重载s[1] = '1' 是进行的写操作; 可以对=进行重载s[1] = '1' . char = char 两个char是不能被重载的,因为 运算符重载的第一条规则,参数必须要有一个自定义类型或者enumCharProxy = char就可以重载了 可以先重载一下[],让他返回一个CharProxy对象,然后重载CharProxy的operator=和operator<<函数CharProxy operator[](size idx);CharProxy = char;*/// 读操作cout << endl << endl << "对s1[1]执行读操作操作" << endl;cout << s1[1] << endl; // 首先会调用s1.operator[](1)返回一个CharProxy对象,然后调用CharProxy的operator<<()函数cout << "s1 = " << s1 << endl;cout << "s2 = " << s2 << endl;cout << "s3 = " << s3 << endl;cout << "s1 RefCount= " << s1.getRefCount() << endl;cout << "s2 RefCount= " << s2.getRefCount() << endl;cout << "s3 RefCount= " << s3.getRefCount() << endl;printf("s1`address = %p\n", s1.c_str());printf("s2`address = %p\n", s2.c_str());printf("s3`address = %p\n", s3.c_str());return 0;
}//https://www.bilibili.com/video/BV1VM4m12754?t=1190.2&p=58
上面会出现,双友元声明,可以只重载operator=,不重载<< 和一个类型转换函数
-
//双友元的设置 std::ostream& operator<<(std::ostream& os, const String::CharProxy& rhs) // 注意这个函数既要左CharProxy的友元也要作为String的友元(不然上面的代码const String::CharProxy& ch处会报错) {os << rhs._self._pstr[rhs._idx];return os; }// cout<<s1[1] CharProxy-> char
-
改为
-
String::CharProxy::operator char() // 注意类型转换函数在类外的定义的形式operator char都放在最后 {return _self._pstr[_idx]; }
-
string的实现
#include<iostream>
#include<cstring>
#include<vector>
using std::cout;
using std::endl;class String
{friend bool operator==(const String& lhs, const String& rhs);friend bool operator!=(const String& lhs, const String& rhs);friend bool operator>(const String& lhs, const String& rhs);friend bool operator<(const String& lhs, const String& rhs);friend bool operator<=(const String& lhs, const String& rhs);friend bool operator>=(const String& lhs, const String& rhs);friend std::ostream& operator<<(std::ostream& os, const String& s);friend std::istream& operator>>(std::istream& is, String& s);
public:String();String(const char* pstr);String(const String& rhs);String& operator=(const String& rhs);String& operator=(const char* pstr);String& operator+=(const String& rhs);String& operator+=(const char* pstr);char& operator[](std::size_t index); // 非const调用char& operator[](std::size_t index) const;// const对象调用std::size_t size()const;const char* c_str()const;
private:char* _pstr;};
std::size_t String::size()const
{return strlen(this->_pstr);
}
const char* String::c_str()const
{return this->_pstr;
}
String::String() :_pstr(nullptr) // 后面的操作需要判空
{cout << "String()" << endl;
}
String::String(const char* pstr) :_pstr(new char[strlen(pstr)+1]())
{strcpy(this->_pstr,pstr);
}String::String(const String& rhs) :_pstr(new char[strlen(rhs._pstr) + 1])
{cout << "String(const String& rhs)" << endl;strcpy(this->_pstr, rhs._pstr);
}String& String::operator=(const String& rhs)
{if (&rhs != this){delete[] this->_pstr;this->_pstr = nullptr;this->_pstr = new char[strlen(rhs.c_str() + 1)]();strcpy(this->_pstr, rhs.c_str());}return *this;
}
String& String::operator=(const char* pstr)
{String tmp(pstr);*this = tmp; // 调用String的operator=()函数。return tmp;
}
String& String::operator+=(const String& rhs)
{int len = this->size() + rhs.size() + 1;char* p = new char[len + 1] ();strcpy(p,this->c_str());strcat(p,rhs.c_str());delete[] this->_pstr;this->_pstr = p;return *this;
}
String& String::operator+=(const char* pstr)
{//char* p = new char[this->size()+strlen(pstr) + 1]();//strcpy(p, this->c_str());//strcat(p, pstr);//delete[] this->_pstr;//this->_pstr = p;String tmp(pstr);*this += tmp; // 调用operator+=(const String& rhs)return *this;
}
char& String::operator[](std::size_t index)
{if (index < this->size()){return this->_pstr[index];}else {static char nullchar = '\0';return nullchar;}
}
char& String::operator[](std::size_t index) const
{if (index < this->size()){return this->_pstr[index];}else {static char nullchar = '\0';return nullchar;}
}bool operator==(const String& lhs, const String& rhs)
{return !strcmp(lhs.c_str(),rhs.c_str());
}
bool operator!=(const String& lhs, const String& rhs)
{return strcmp(lhs.c_str(), rhs.c_str());
}bool operator>(const String& lhs, const String& rhs)
{return strcmp(lhs.c_str(),rhs.c_str());
}
bool operator<(const String& lhs, const String& rhs)
{return strcmp(lhs.c_str(), rhs.c_str());
}
bool operator<=(const String& lhs, const String& rhs)
{return strcmp(lhs.c_str(), rhs.c_str());
}
bool operator>=(const String& lhs, const String& rhs)
{return strcmp(lhs.c_str(), rhs.c_str());
}std::ostream& operator<<(std::ostream& os, const String& s)
{os << s.c_str();
}
std::istream& operator>>(std::istream& is, String& s)
{if (s._pstr){delete s._pstr;s._pstr = nullptr;}std::vector<char> buffer;char ch;while ((ch = is.get()) != '\n'){buffer.push_back(ch);}s._pstr = new char[buffer.size() + 1]();strncpy(s._pstr,&buffer[0],buffer.size());return is;
}