如图所示,str1和str2指向的内存中内容是一样的,如果系统浅拷贝的话,一个释放后,另一个释放时找不到要是放的内存;如果自己实现深拷贝,会出现内存浪费。所以实现string类的写时拷贝。
引用计数放在什么地方合适呢?
1、放在类中
作为普通成员变量,那么每个对象中都有一个count,不能实现共用;
作为静态成员变量,定义str1和str2后,count=2,那么再定义string str3(“world”);后,count又会等于1。
也就是说,放在类中不能实现。
2、放在内存中
如果出现str1[1] = ‘s’;这样的情况呢?
这个时候会修改str1的内容,那么就需要实现深拷贝,所以在operator[]中实现深拷贝。
#include<iostream>
using namespace std;
#pragma warning(disable:4996);
class String
{
public:
String(char* ptr = NULL)
:mptr(new char[strlen(ptr) + 5])//加上'\0'和引用计数的长度
{
mptr += 4;//找到存放数据的位置
strcpy(mptr, ptr);
getRefCount(mptr) = 1;
}
String(const String& rhs)
:mptr(rhs.mptr)
{
++getRefCount(mptr);
}
String& operator=(const String& rhs)
{
if (this != &rhs)
{
Release();
mptr = rhs.mptr;
++getRefCount(mptr);
}
return *this;
}
char& operator[](int index)
{
if (getRefCount(mptr) > 1)//如果只有一个指针指向的话,直接修改就可以
{
char* ptr = mptr;
--getRefCount(ptr);
mptr = new char[strlen(ptr) + 5];
mptr += 4;
getRefCount(mptr) = 1;
strcpy(mptr, ptr);
}
return mptr[index];
}
~String()
{
Release();
}
private:
void Release()
{
if (--getRefCount(mptr) == 0)
{
delete[] (mptr - 4);
}
}
int& getRefCount(char* ptr)
{
return *(int*)(ptr - 4);
}
char* mptr;
};
int main()
{
String str1("hello");
String str2(str1);
String str3("world");
str3 = str1;
str1[0] = 's';
return 0;
}