您的位置:首页 > 编程语言 > C语言/C++

模拟实现C++STL中的string类

2017-08-06 21:10 253 查看
       在C++中的字符串有C语言继承过来的char* 型的,还有就是C++STL中的string型的了。

       C++中的string类在实现的过程中会遇到一些特别的地方。

比如:深浅拷贝、写时拷贝、引用计数等一些概念

浅拷贝:

       默认的拷贝构造函数(值拷贝)。会出现两个指针维护同一块空间的问题,可能会一个指针释放空间导致另一个指针访问非法空间。

深拷贝:

      自己构造拷贝构造函数,即自己开辟新空间再用memcpy进行值拷贝,用指针维护新开辟的空间

写时拷贝:

      在浅拷贝的基础上增加引用计数,若要修改同一块空间时,再开辟新空间并进行值拷贝

      写时拷贝即实现operator[],缺点是用[]读的时候也进行拷贝

深浅拷贝的应用:

VS的string:用深拷贝实现。

Linux中的string:用带引用计数的浅拷贝实现,operator[]时进行写时拷贝

注:STL库中的string类有一个Buffer:

小于16个字符的string以空间换时间

大于16个字节的存在_ptr指针指向的另外空间

string类源码:

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cassert>
using namespace std;
//相同字符串指向同一块空间,用一个引用计数来统计该字符串被引用的次数,并且增加了写时拷贝
class String
{
friend ostream& operator<<(ostream& os, const String& s);
public:
//String()
//	:_str(new char[1])
//	, _refCount(new int(1));
//{
//	_str[0] = '\0';
//}
String(const char *str = "")     //默认字符串为空字符串
:_str(new char[strlen(str) + 1])
, _refCount(new int(1))
{
strcpy(_str, str);
cout << "String(const char *str)" << endl;
}

String(String& s)  //拷贝构造函数
:_str(s._str)
4000

, _refCount(s._refCount)
{
++(*_refCount);
}
//传统的写法(s1=s2)
String& operator=(const String& s)
{
//1、s1和s2指向同一块空间(不处理)
//2、减减s1指向空间的引用计数,若s1是最后一块管理对象,则释放s1
if (_str != s._str)
{
this->Release();

this->_str = s._str;
this->_refCount = s._refCount;
++(*_refCount);
}
return *this;
}
//现代的写法
String& operator=(String s)   //拷贝s时引用计数已经加1
{
swap(_str, s._str);
swap(_refCount, s._refCount);
return *this;
}
void Release()
{
if (--(*_refCount) == 0)
{
cout << "delete" << endl;
delete[] _str;
delete _refCount;
}
}
//String* this
char& operator[](size_t index)
{
//写时拷贝
CopyOnWrite();  //缺点:读的时候也会进行拷贝

assert(index < strlen(_str));
return _str[index];
}

//const String* this
const char& operator[](size_t index) const   //常成员函数,当访问常成员变量时调用
{
assert(index < strlen(_str));
return _str[index];
}

void CopyOnWrite()
{
//引用计数大于1时需要进行拷贝
if ((*_refCount)>1)
{
char* tmp = new char[strlen(_str) + 1];
strcpy(tmp, _str);
--(*_refCount);

_refCount = new int(1);
_str = tmp;
}
}

~String()
{
Release();
}

char* GetStr()
{
return _str;
}
private:
char* _str;
int* _refCount;   //引用计数的指针
};

ostream& operator<<(ostream& os, const String& s)   //重载string的输出符号
{
os << s._str;
return os;
}
int main()
{
const String str1("123456");
String str2="123";
String str3;
//str2 = str1;
str3 = str2;

String str4("abcdef");
String str5(str4);

cout << str1[3] << endl;
cout << str2 << endl;
cout << str3 << endl;

cout << str4 << endl;
cout << str5 << endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: