模仿实现C++库函数----String 类----用 写时拷贝   实现

#define _CRT_SECURE_NO_WARNINGS 1

#include<iostream>

#include<assert.h>

#define DEFAULTNUME 3

using namespace std;

class String

{

public:

int& GetCount()

{

return *(((int *)_str) - 1);

}

char* GetStr()

{

return _str;

}

//找到字符 ch  并返回它的下标

int Find(char ch)

{

if (_str == NULL)

{

return -1;

}

else

{

int count = 0;

char* str = _str;

while (str && count < _size)

{

if (*str == ch)

{

return count;

}

str++;

count++;

}

}

return -1;

}

//实现下标访问

char& operator[](int pos)

{

char* cur = _str;

cur = cur + pos ;

return *cur;

}

bool operator<(const String& s)

{

char* pSourse = this->_str;

char* pDest = s._str;

if (pSourse == NULL)

{

return false;

}

else if (pDest == NULL)

{

return true;

}

else

{

while ((*pSourse != NULL) && (pDest != NULL))

{

if (*pSourse < *pDest)

{

return true;

}

else if (*pSourse > *pDest)

{

return false;

}

else

{

pSourse++;

pDest++;

}

}

}

if (*pSourse == NULL && *pDest != NULL)

{

return true;

}

else

{

return false;

}

}

bool operator==(const String& s)

{

char* pSource = _str;

char* pDest = s._str;

if (_size == s._size)

{

while (*pSource == *pDest && *pSource != NULL && *pDest != NULL)

{

pSource++;

pDest++;

}

if (*pSource == NULL && *pDest == NULL)

{

return true;

}

}

return false;

}

bool operator>(const String& s)

{

return !((*this < s) && (*this == s));

}

bool operator>=(const String& s)

{

return ((*this > s) && (*this == s));

}

bool operator<=(const String& s)

{

return ((*this < s) && (*this == s));

}

bool operator!=(const String& s)

{

return !(*this == s);

}

char* CheckCapacity(int capacity)

{

if (capacity > _capacity)

{

char* cur = new char[capacity + DEFAULTNUME];

return cur;

}

return _str;//>>>>>>>>>>>>>>>>>>>改

}

void  Insert(int pos, const char* s)

{

*(((int *)_str) - 1) -= 1;

int len = strlen(s);

char* p = CheckCapacity(_size + len + 1);

strcpy(p, _str);

_str = p;

p = NULL;

//移动原字符串  空出来空间给待插入的字符串

int moveCount = _size - pos  + len + 1;// moveCount 为移动次数

int i = _size;//  i  为移动的元素位置

while (moveCount--)//把pos位置及pos后面的  字符 集体向后移一位

{

_str[i + len] = _str[i];

i--;

}

//插入待插入的字符串

//int insertCount = len;   //  insertCount  为字符插入次数

//int posSource = pos;//  posSource 为原字符串的下标

//int posDest = 0;// posDest 为待插入的字符串s的下标

//while (insertCount--)

//{

// _str[posSource - 1] = s[posDest];

// posSource++;

// posDest++;

//}                            //>>>用strncpy就可以实现(多注意常用的库函数啊!)

char* tem = _str + pos - 1;

strncpy(tem, s,len);

_size += len;

_capacity = _size + 4; //4 为 ‘\0‘ + DEFAULTNUME 的个数

}

void  Insert(size_t pos, const char ch)

{

*(((int *)_str) - 1) -= 1;

char* p = new char[_capacity + 1];

strcpy(p, _str);

_str = p;

p = NULL;

int count = _size - pos + 2;// count 为移动次数

int i = _size;//移动的元素位置

while (count--)//把pos位置及pos后面的  字符 集体向后移一位

{

_str[i + 1] = _str[i];

i--;

}

_str[pos - 1] = ch;

_size++;

_capacity = _size + 4; //4 为 ‘\0‘ + DEFAULTNUME 的个数

}

String& operator+=(const String& s)

{

*(((int *)_str) - 1) -= 1;

char* cur = CheckCapacity(_size + s._size + 5);

cur = cur + 4;

strcpy(cur, _str);//拷贝原字符串

_str = cur;

Insert(_size + 1, s._str);//拷贝s._str字符串

*((int*)cur - 1) = 1;

cur = NULL;

_size += s._size;

_capacity = _size + 4;  //4 为 ‘\0‘ + DEFAULTNUME 的个数

return *this;

}

public:

String(char* str = "")

:_str(new char[_size + 5])

{

_str = _str + 4;

strcpy(_str, str);

_size = strlen(str);

_capacity = _size + 1;

//GetCount() = 1;//  为什么 错了?

*(((int *)_str) - 1) += 1;//用++为什么错了

}

String(const String& s)

{

_str = s._str;

_size = s._size;

_capacity = _size + 1;

int count = GetCount();

GetCount()++;

}

~String()

{

if (--GetCount() == 0 && _str != NULL)

{

delete[] _str;

_str = NULL;//>>>>>>>>>>>>>>>>>改

}

}

String& operator=(const String& s)

{

if (this != &s)

{

_str = s._str;

_size = s._size;

_capacity = _size + 1;

int count = GetCount();

//GetCount()++;

*(((int *)_str) - 1) += 1;

}

return *this;

}

private:

void Check(int a);//实现引用计数

char* _str;

int _size;

int _capacity;

};

//test 构造函数  拷贝构造函数 析构函数 赋值操作符重载 引用计数

void test1()

{

String s1("abcd");

cout << s1.GetStr() << endl;

String s2 = s1;

cout << s2.GetStr() << endl;

String s3;

cout << s3.GetStr() << endl;

s3 = s1;

cout << s3.GetStr() << endl;

}

//test  Find  operator[](只读操作)

void test2()

{

String s1("abcdefg");

cout << s1.Find(‘b‘) << endl;

cout << s1.Find(‘g‘) << endl;

cout << s1.Find(‘h‘) << endl;

cout << s1[2] << endl;

cout << s1[6] << endl;

cout << s1[9] << endl;

}

//test  operator< operator== operator>

//test  operator<=  operator>= operator!=

void test3()

{

String s1("abcd");

String s2("abc");

String s3("abcd");

String s4("acd");

cout << (s2 < s1) << endl;

cout << (s1 < s2) << endl;

cout << (s1 < s3) << endl;

cout << (s1 < s4) << endl;

cout << (s1 == s3) << endl;

cout << (s1 == s2) << endl;

}

//test  operator+=  Insert

void test4()

{

String s1("tan");

String s2("xiaohui is superman");

cout << (s1 += s2).GetStr() << endl;

//s1.Insert(2, "ooooo");

//cout << s1.GetStr() << endl;

s1.Insert(4, ‘-‘);

cout << s1.GetStr() << endl;

}

int main()

{

//test1();

//test2();

//test3();

test4();

system("pause");

return 0;

}

时间: 2024-10-05 09:06:55

模仿实现C++库函数----String 类----用 写时拷贝   实现的相关文章

string类的写时拷贝

由于浅拷贝使多个对象共用一块内存地址,调用析构函数时导致一块内存被多次释放,导致程序奔溃. 实现string类的时候通常显示的定义拷贝构造函数和运算符重载函数. 由于释放内存空间,开辟内存空间时花费时间,因此,在我们在不需要写,只是读的时候就可以不用新开辟内存空间,就用浅拷贝的方式创建对象,当我们需要写的时候才去新开辟内存空间.这种方法就是写时拷贝. 在构造函数中开辟新的空间时多开辟4个字节的空间,用来存放引用计数器,记录这快空间的引用次数. [cpp] view plain copy #inc

string类的写时才拷贝(Copy-On-Write)

写时才拷贝(Copy-On-Write)的原理是什么? Copy-On-Write,其实是使用了一个计数器.当第一个类构造时,计数器初始值为1,string类的构造函数会根据传入的参数从堆上分配内存,当其他类需要这块内存时,这个计数器自动累加.当有析构函数时,这个计数器会减1,直到当计数器为1时,即最后一个类析构.此时,程序才会真正的delete这块从堆上分配的内存. 2.  string在什么情况下会发生写时才拷贝(Copy-On-Write)? 当string类中发生内存共享且内容发生改变时

String 类的实现(4)写时拷贝浅析

由于释放内存空间,开辟内存空间时花费时间,因此,在我们在不需要写,只是读的时候就可以不用新开辟内存空间,就用浅拷贝的方式创建对象,当我们需要写的时候才去新开辟内存空间.这种方法就是写时拷贝.这也是一种解决由于浅拷贝使多个对象共用一块内存地址,调用析构函数时导致一块内存被多次释放,导致程序奔溃的问题.这种方法同样需要用到引用计数:使用int *保存引用计数:采用所申请的4个字节空间. 1 #include<iostream> 2 #include<stdlib.h> 3 using

C++ String类写时拷贝

    维基百科:     写入时复制(英语:Copy-on-write,简称COW)是一种计算机程序设计领域的优化策略.其核心思想是,如果有多个调用者(callers)同时要求相同资源(如内存或磁盘上的数据存储),他们会共同获取相同的指针指向相同的资源,直到某个调用者试图修改资源的内容时,系统才会真正复制一份专用副本(private copy)给该调用者,而其他调用者所见到的最初的资源仍然保持不变.这过程对其他的调用者都是透明的(transparently).此作法主要的优点是如果调用者没有修

标准C++类std::string的内存共享和Copy-On-Write(写时拷贝)

标准C++类std::string的内存共享,值得体会: 详见大牛:https://www.douban.com/group/topic/19621165/ 顾名思义,内存共享,就是两个乃至更多的对象,共同使用一块内存: 1.关于string的内存共享问题: 通常,string类中必有一个私有成员,其是一个char*,用户记录从堆上分配内存的地址,其在构造时分配内存,在析构时释放内存. 因为是从堆上分配内存,所以string类在维护这块内存上是格外小心的,string类在返回这块内存地址时,只返

简单的String类实现及写时拷贝

#include<iostream> using namespace std; class String { public: /*String(const char* str=" ") :_str(new char[strlen(str)+1]) { strcpy(_str, str); } */ String(const char* str = " ") { if (str == NULL) { _str = new char; _str[0] = '

string类的深浅拷贝,写时拷贝

浅拷贝:多个指针指向同一块空间,多次析构同一块内存空间,系统会崩溃.(浅拷贝就是值拷贝) 深拷贝:给指针开辟新的空间,把内容拷贝进去,每个指针都指向自己的内存空间,析构时不会内存崩溃. #include <iostream> #include <string> using namespace std; class String { public: String(const char*str) :_str(new char [strlen(str)+1]) { strcpy(_str

C++ String 写时拷贝

当类里面有指针对象时,采用简单的赋值浅拷贝,使得两个指针指向同一块内存,则析构两次,存在内存奔溃的问题,因此浅拷贝中利用引用计数. //引用计数浅拷贝 class String { public:  String(char*str = "")   :_str(new char[strlen(str) + 1])   , _pRefCount(new int(1))  {}  String(const String & s)   :_str(s._str)   , _pRefCo

String写时拷贝实现

头文件部分 1 /* 2 版权信息:狼 3 文件名称:String.h 4 文件标识: 5 摘 要:对于上版本简易的String进行优化跟进. 6 改进 7 1.(将小块内存问题与大块分别对待)小内存块每个对象都有,当内存需求大于定义大小时利用动态分配 8 2.实现大块内存的写时拷贝功能,提高效率,优化空间利用 9 3.类似new[]实现机制:将动态内存块大小信息保存为隐藏“头” 10 11 当前版本:1.2 12 修 改 者:狼 13 完成日期:2015-12-12 14 15 取代版本:1.