关于String类的模拟实现:
一.深拷贝:
1.传统写法:
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <stdlib.h>
#include <string>
#include <assert.h>
using namespace std;
class String
{
public:
//构造函数
String(const char* str = "")
{
if (str == nullptr)
{
assert(false);
return;
}
_str = new char[strlen(str) + 1];
strcpy(_str, str);
}
//析构函数
~String()
{
if (_str)
{
delete[] _str;
_str = nullptr;
}
}
//赋值运算符重载
String& operator=(const String& s)
{
if (&s != this)
{
delete[] this->_str;
_str = new char[strlen(s._str) + 1];
strcpy(_str, s._str);
}
//防止连续赋值
return *this;
}
//拷贝构造
String(const String& s)
:_str(new char[strlen(s._str) + 1])
{
strcpy(_str, s._str);
}
private:
char* _str;
};
2.现代写法:
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <stdlib.h>
#include <string>
#include <assert.h>
using namespace std;
class String
{
public:
String(const char* str = "")
{
if (nullptr == str)
str = "";
_str = new char[strlen(str) + 1];
strcpy(_str, str);
}
String(const MyString& s)
{
MyString str(s._str);
swap(_str, str._str);
}
String& operator=(MyString& s)
{
swap(_str, s._str);
return *this;
}
~String()
{
if (_str)
{
delete[] _str;
_str = nullptr;
}
}
private:
char* _str;
};
二.引用计数:
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <stdlib.h>
#include <string>
#include <assert.h>
using namespace std;
class String{
public:
//构造函数
String(const char* ptr = "")
:_count(new int[0])
, _ptr(new char[strlen(ptr)+1])
{
if (ptr == NULL)
{
_ptr = new char[1];
*_ptr = '\0';
}
else
strcpy(_ptr, ptr);
*_count = 1;
}
//拷贝构造函数
String(const string& s)
:_count(s._count)
{
_ptr = (char*)(s._ptr);
_count = s._count;
(*_count)++;
}
String& operator=(const string& s)
{
if (_ptr!=s._ptr)
{
_ptr = s._ptr;
_count = s._count;
(*_count)++;
}
return *this;
}
~String()
{
if (_ptr == NULL)
return;
else
{
if (--(*_count)==0)
{
delete[] _ptr;
delete[] _count;
_ptr = NULL;
_count = NULL;
}
}
}
private:
char* _ptr;
int* _count;
};
三.写时拷贝:
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <stdlib.h>
#include <string>
#include <assert.h>
using namespace std;
class string
{
public:
string(const char* ptr="")
:_ptr(new char[strlen(ptr)+4+1])//每次多创建4个空间来存放当前地址有几个对象
{
if (_ptr == NULL)
{
(*(int*)_ptr) = 1;//前四个字节拿来计数
_ptr += 4;
*_ptr = '\0';
}
else
{
(*(int*)_ptr) = 1;
_ptr += 4;
strcpy(_ptr, ptr);
}
}
string(const string& s)
:_ptr(s._ptr)
{
++(*(int*)(_ptr - 4));//向前偏移4个字节将计数加1
}
string& operator=(const string& s)
{
if (_ptr != s._ptr)
{
if (--(*(int*)(_ptr-4)) == 0)
{
delete[] _ptr;
_ptr = NULL;
}
_ptr = s._ptr;
++(*(int*)(_ptr - 4));
}
}
~string()
{
if (_ptr == NULL)
{
return;
}
else
{
if (--(*(int*)(_ptr - 4)) == 0)
{
delete[] (_ptr-4);
_ptr = NULL;
}
}
}
char& operator[](size_t index)//下标访问操作符重载
{
assert(index >= 0 && index < strlen(_ptr));
if ((*(int*)(_ptr - 4))>1)//多个对象指向同一块空间
{
char* tmp = new char[strlen(_ptr) + 4 + 1];//新开辟一块空间
tmp += 4;//向后偏移4
strcpy(tmp,_ptr);
--(*(int*)(_ptr - 4));//将原来空间的计数器减1
_ptr = tmp;//将当前对象指向临时空间
*((int*)(_ptr - 4)) = 1;//将新空间的计数器变为1
}
return _ptr[index];
}
private:
char* _ptr;
};