#define _CRT_SECURE_NO_WARNINGS 
 
#include <iostream>
using namespace std;
#include <Windows.h>
//深拷贝
class String
{
public:
String(const char* pData)
: _pData(new char[strlen(pData) + 1])
{
strcpy(_pData, pData);
}
 
String(const String& s)//拷贝构造,深拷贝,指针传递
: _pData(NULL)
{
String temp(s._pData);
std::swap(_pData, temp._pData);
}
 
String& operator=(String s)//赋值运算符重载,深拷贝,值传递
{
std::swap(_pData, s._pData);
return *this;
}
~String()
{
if (NULL != _pData)
{
delete[] _pData;
_pData = NULL;
}
}
private:
char* _pData;
};//深拷贝


//引用计数
namespace COW
{
class String
{
public:
String(const char* pData)
: _pData(new char[strlen(pData) + 1])
, _refCount(new int)
{
*_refCount = 1;
strcpy(_pData, pData);
}
 
// String s2(s1);
String(String& s)//s1和s2共用
: _pData(s._pData)//指向同一空间
, _refCount(s._refCount)//共用同一段引用计数
{
++(*_refCount);
}
 
// s1 = s2;
String& operator=(String s)
{
if (this != &s)
{
if (--(*_refCount) == 0)//检查这块空间是否只有自己使用
{
delete[] _pData;
delete _refCount;//检测完释放归还操作系统
}
 
_pData = s._pData;//再指向另一块空间
_refCount = s._refCount;
++(*_refCount);
}
 
return *this;
}
 
~String()
{
if (--(*_refCount) == 0)
{
delete[] _pData;
delete _refCount;
}
}
 
private:
char* _pData;
int* _refCount;
};
}
//优化引用计数
class String
{
public:
	String(const char* pData)
		: _pData(new char[strlen(pData) + 5])
	{
		*((int*)_pData) = 1;
		_pData += 4;  // _pData = _pData + sizeof(char)*4;
		strcpy(_pData, pData);
		
	}

	// s2(s1);
	String(const String& s)
		: _pData(s._pData)
	{
		++GetRef();
		strcpy(_pData, s._pData);
	}

	// s2 = s3;
	String& operator=(const String& s)
	{
		if (this != &s)
		{
			if (--GetRef() == 0)
			{
				delete[](_pData - 4);
			}

			_pData = s._pData;
			++GetRef();
		}
		return *this;
	}

	~String()
	{
		if (--GetRef() == 0)
		{
			delete[](_pData - 4);
		}
	}

private:
	int& GetRef()
	{
		return (*((int*)(_pData - 4)));
	}
private:
	char*_pData;
};
 
测试引用计数和深拷贝所用时间
class Time
{
public:
Time()
{
begin = GetTickCount();
}
 
~Time()
{
int end = GetTickCount();
cout << "end - begin = " << end - begin << endl;
}
 
private:
int begin;
};
 
 
void FunTest()
{
Time t;
COW::String s1("12345");//引用计数
COW::String s2(s1);
 
 for (int iIdx = 0; iIdx < 1000000; ++iIdx)
 {
 s1 = s2;
 }
}
 
 
 
void FunTest2()
{
Time t;
 
String s1("123456789");
String s2("2345678");
for (int iIdx = 0; iIdx < 1000000; ++iIdx)
{
s1 = s2;
}
}
int main()
{
FunTest();
FunTest2();
system("pause");
return 0;
}