string类型的最重要技术实现是引用计数和浅拷贝。
写时复制,读时共享,类似于fork()函数,来创建子进程。
temp String::operator[](size_t idx)
{
return temp(*this, idx);
}
//---------------------1------------------------
实现方法:
- 1:将[]重载延时发动,通过传入一个对象的形式,把[]和=抽离开来
- 2:遇到=重载,就是写操作,否则是读操作
- 3:传递回一个中间对象temp,并且将temp的<<运算符重载,可以正常输出temp[x]
前面存放引用计数是因为,一旦string发生扩容,或者继续写入的时候,会造成引用计数存储的被覆盖。
//----------------------2--------------------------
char &operator=(char c)
{
if (*(int*)(this->m_String.c_str() - 4) > 1)
{
char *p = new char[strlen(this->m_String._pstr) + 5]() + 4;//往后偏移到数据指针
strcpy(p, this->m_String._pstr);
--*(int*)(this->m_String.c_str() - 4);//将引用计数--
m_String._pstr = p;
++*(int*)(this->m_String.c_str() - 4);//自成一派,引用计数为+1
m_String.c_str()[m_index] = c;
}
return m_String.c_str()[m_index];//延时发动成功,返回单个字符即可
}
//---------------------------3---------------------------
friend ostream& operator<<(ostream& os, const temp &rhs)
{
os << rhs.m_String._pstr[rhs.m_index];
return os;
}
#include <string.h>
#include <iostream>
using namespace std;
class String;
class temp;
class String
{
friend temp;
public:
String()
: _pstr(new char[5]() + 4)
{
cout << "String()" << endl;
*(int *)(_pstr - 4) = 1;
}
String(const char *pstr)
: _pstr(new char[strlen(pstr) + 5]() + 4)
{
cout << "String(const char *)" << endl;
strcpy(_pstr, pstr);
*(int *)(_pstr - 4) = 1;
}
String(const String &rhs)
: _pstr(rhs._pstr)
{
cout << "String(const String &)" << endl;
++*(int *)(_pstr - 4);
}
String &operator=(const String &rhs)
{
cout << "String &operator=(const String &)" << endl;
if (this != &rhs)//1、自复制
{
--*(int *)(_pstr - 4);//2、释放左操作数
if (0 == *(int *)(_pstr - 4))
{
delete[](_pstr - 4);
}
_pstr = rhs._pstr;//3、浅拷贝
++*(int *)(_pstr - 4);
}
return *this;//4、返回*this
}
//s3[0] = 'H';
temp operator[](size_t idx);
~String()
{
cout << "~String()" << endl;
--*(int *)(_pstr - 4);
if (0 == *(int *)(_pstr - 4))
{
delete[](_pstr - 4);
}
}
char *c_str()
{
return _pstr;
}
int getRefCount() const
{
return *(int *)(_pstr - 4);
}
size_t size() const
{
return strlen(_pstr);
}
friend std::ostream &operator<<(std::ostream &os, const String &rhs);
friend ostream& operator<<(ostream& os, const temp &rhs);
private:
char *_pstr;
};
std::ostream &operator<<(std::ostream &os, const String &rhs)
{
if (nullptr != rhs._pstr)
{
os << rhs._pstr;
}
return os;
}
class temp
{
public:
temp(String& s, size_t idx);
char &operator=(char c)
{
if (*(int*)(this->m_String.c_str() - 4) > 1)
{
char *p = new char[strlen(this->m_String._pstr) + 5]() + 4;//往后偏移到数据指针
strcpy(p, this->m_String._pstr);
--*(int*)(this->m_String.c_str() - 4);
m_String._pstr = p;
++*(int*)(this->m_String.c_str() - 4);
m_String.c_str()[m_index] = c;
}
return m_String.c_str()[m_index];
}
friend ostream& operator<<(ostream& os, const temp &rhs)
{
os << rhs.m_String._pstr[rhs.m_index];
return os;
}
private:
String &m_String;
size_t m_index;
};
void test()
{
String s1("hello");
cout << "s1 = " << s1 << endl;
printf("s1's address: %p\n", s1.c_str());
printf("s1's RefCount = %d\n", s1.getRefCount());
cout << endl;
String s2 = s1;
cout << "s1 = " << s1 << endl;
cout << "s2 = " << s2 << endl;
printf("s1's address: %p\n", s1.c_str());
printf("s2's address: %p\n", s2.c_str());
printf("s1's RefCount = %d\n", s1.getRefCount());
printf("s2's RefCount = %d\n", s2.getRefCount());
cout << endl;
String s3("world");
cout << "s3 = " << s3 << endl;
printf("s3's address: %p\n", s3.c_str());
printf("s3's RefCount = %d\n", s3.getRefCount());
cout << endl << "执行s3 = s1操作" << endl;
s3 = s1;
cout << "s1 = " << s1 << endl;
cout << "s2 = " << s2 << endl;
cout << "s3 = " << s3 << endl;
printf("s1's address: %p\n", s1.c_str());
printf("s2's address: %p\n", s2.c_str());
printf("s3's address: %p\n", s3.c_str());
printf("s1's RefCount = %d\n", s1.getRefCount());
printf("s2's RefCount = %d\n", s2.getRefCount());
printf("s3's RefCount = %d\n", s3.getRefCount());
cout << endl << "执行s3 = s1操作" << endl;
s2[1] = 'H';
cout << "s1 = " << s1 << endl;
cout << "s2 = " << s2 << endl;
cout << "s3 = " << s3 << endl;
printf("s1's address: %p\n", s1.c_str());
printf("s2's address: %p\n", s2.c_str());
printf("s3's address: %p\n", s3.c_str());
printf("s1's RefCount = %d\n", s1.getRefCount());
printf("s2's RefCount = %d\n", s2.getRefCount());
printf("s3's RefCount = %d\n", s3.getRefCount());
#if 1
cout << endl << "对s3[0]进行读操作"<<s3[0] << endl;
s3[0] = 'H';
cout << s1[0] << endl;
cout << "s1 = " << s1 << endl;
cout << "s2 = " << s2 << endl;
cout << "s3 = " << s3 << endl;
printf("s1's address: %p\n", s1.c_str());
printf("s2's address: %p\n", s2.c_str());
printf("s3's address: %p\n", s3.c_str());
printf("s1's RefCount = %d\n", s1.getRefCount());
printf("s2's RefCount = %d\n", s2.getRefCount());
printf("s3's RefCount = %d\n", s3.getRefCount());
#endif
}
int main(int argc, char **argv)
{
test();
return 0;
}
temp String::operator[](size_t idx)
{
return temp(*this, idx);
}
temp::temp(String & s, size_t idx)
:m_String(s)
,m_index(idx)
{
}