Sting类的实现

26 篇文章 0 订阅

一.浅拷贝

class String
{
public:
String(const char *str ="")
:_str(new char[strlen(str) + 1])
{
strcpy(_str, str);
}
s2 (s1)
String(const String &s)
{
size_t len = strlen(s._str) + 1;
_str = new char[len];
strcpy(_str, s._str);
}
//s2 =s1;
String&operator =(const String & s)
{
if (this != &s)
{
_str = s._str;
}
return *this;
}
~String()
{
if (_str)
{
delete[]_str;
_str = NULL;
}
}
char *GetStr()
{
return _str;
}
private:
char *_str;
};
int main()
{
String s1("hello");
String s2 = s1;
system("pause");
return 0;
}

简单赋值的浅拷贝是指:s1和s2两个对象指向同一块内存,析构时会析构两次。这是系统会出现崩溃。

如何解决?


二.深拷贝

就是给s2构造一个和s1一样大的空间,将s1的数据拷贝进去,这样是s1和s2指向各自的空间,析构各自的空间就不会出现出现内存泄露。
拷贝构造时,这时会有两种方法。

方法一:
是先释放s1的内存,把内存还给操作系统,然后再创建新的空间,把s1中的hello拷进去,似乎可行。

/s2 = s1
String&operator =(const String & s)
{
if (this != &s)
{
delete[]_str;
size_t len = strlen(s._str);
this->_str = new char[len + 1];
memcpy(_str, s._str, len + 1);
}
return *this;
}
但是这样会造成一种情况是,破坏了s1,s2开辟空间失败的话,会造成内存的泄露。
方法二:
先开辟和s1一样大空间,然后将s1的数据拷贝到s2,最后释放s1的空间

//s2 =s1;
String&operator =(const String & s)
{
if (this != &s)
{
size_t len = strlen(s._str);
char *tmp = new char[strlen(s._str) + 1];
memcpy(_str, s._str, len + 1);
delete[] _str;
_str = tmp;
}
return *this;
}

三,常见面试题之string的实现

传统写法:

class String
{
public:
String(const char *str ="" )
:_str(new char[strlen(str) + 1])
{
strcpy(_str, str);
}
//s2 (s1)
String(const String &s)
{
size_t len = strlen(s._str) + 1;
_str = new char[len];
strcpy(_str, s._str);
}
//s3 =s1;
String&operator =(const String & s)
{
if (this != &s)
{
char *tmp = new char[strlen(s._str) + 1];
delete[] _str;
memcpy(_str, s._str, len + 1);
_str = tmp;
}
return *this;
}
~String()
{
if (_str)
{
delete[]_str;
_str = NULL;
}
}
char *GetStr()
{
return _str;
}
private:
char *_str;
};
int main()
{
String s1("hello");
String s2 = s1; 
system("pause");
return 0;
}

//现代写法

class String
{
public:
String(const char *str ="" )
        :_str(new char[strlen(str) + 1])
    {
        strcpy(_str, str);
    }
   // s2 (s1)
    String(const String &s)
        :_str(NULL)
    {
        String tmp(s._str);
        swap(_str, tmp._str);
    }
   // s3 =s1
    String &operator =(const String &s)
    {
        if (this != &s)
        {
            String tmp = (s._str);
            swap(_str, tmp._str);
        }
        return *this;
    }
    //s3=s1
    String &operator=( String s)
    {
        swap(_str, this->_str);
        return *this;
    }
private:
    char *_str;
};
现代写法的优点是先构建一个零时对象tmp,然后将需要拷贝构造的函数与零时构造函数tmp进行交换。提高的效益,且不易出错。

四。模拟实现String的增删查改

#include<iostream>
#include<assert.h> 
using namespace std;
class String
{
public:
String(const char *str = "")
:_size(strlen(str))
,_capacity(_size + 1)
{
_str = new char[_capacity];
memcpy(_str, str, _size+1);
}
//拷贝构造
String(const String &s)
:_str(NULL)
{
String tmp(s._str);
Swap(tmp);
}
//赋值运算符的重载
String &operator = (String s)
{
Swap(s);
return *this;
}
void Swap(String &s)
{
swap(this->_str, s._str);
swap(this->_size, s._size);
swap(this->_capacity, s._capacity);
}
void PushBack(char ch)
{
Insert(_size, ch);
}
void PopBack()
{
assert(_size > 0);
--_size;
_str[_size]= '\0'; 
}
void Insert(size_t pos,char ch)
{
_CheckCapacity(_size + 2);
int end = _size;
while (end >=(int) pos)
{
_str[end + 1] = _str[end];
--end;
}
++_size;
_str[end + 1] = ch;
}
//删除pos位置上的数据
void Erase(size_t pos)
{
assert(pos > 0 && pos < _size);
int i = 0;
for (i = pos; i < _size; ++i)
{
_str[i] = _str[i+1];
}
--_size;
}
//删除pos位置后面n个数据
void Erase(size_t pos, size_t n)
{
assert(pos>0 && pos < _size);
if (pos + n >= _size)
{
_str[pos] = '\0';
}
else
{
int i = 0;
for (i = pos + n; i < _size; ++i)
{
_str[pos++] = _str[i];
}
}
_size -= n;
}
//在pos位置上插入字符串
void Insert(size_t pos, const char* str)
{
size_t len = strlen(str);
_CheckCapacity(_size+ len + 1);
int end = _size;
while (end>= pos )
{
_str[end + len] = _str[end];
--end;
}
char *dst =_str+pos;
while (*dst)
{
*dst = *str;
}
_size += strlen(str);
} 
bool operator>(String &s)
{
char *str1 = _str;
char *str2 = s._str;
while (*str1 && *str2)
{
if (*str1 > *str2)
{
return true;
}
else if (*str1 < *str2)
{
return false;
}
else
{
++*str1;
++*str2;
}
}
// he
// hello
if (*str2)
{
return false;
}
else
{
return true;
}
if (*str1)
{
return true;
}
else
{
return false;
}
}
bool operator ==(String &s)
{
if (_str == s._str)
{
int i = 0;
for (i = 0; i < _size; i++)
{
if (_str != s._str)
return false;
}
return true;
}
return false;
}
bool operator <(String &s)
{
return !(*this == s && *this < s);
}
bool operator >=(String &s)
{
return *this>s&& *this == s;
}
bool operator <=(String &s)
{
return !(*this>s&& *this == s);
}
String operator+(const String &s)
{
String tmp(_str);
tmp.Insert(tmp._size, s._str);
return tmp;
}
String &operator+= (const String &s)
{ 
Insert(this->_size, s._str);
return *this;
}
char& operator[](size_t pos)
{
return _str[pos];
}
size_t Size()
{
return _size;
}
~String()
{
delete[] _str;
}
char *GetStr()
{
return _str;
} 
private:
void _CheckCapacity(size_t NeedSize)
{
if (NeedSize > _capacity)
{
size_t NewCapacity = _capacity * 2;
_str = (char *)realloc(_str, NewCapacity);
_capacity = NewCapacity;
assert(_str);
}
}
private:
char *_str;
size_t _size;
size_t _capacity;
};
void Test1()
{
String s1("hello world");
cout << s1.GetStr() << endl; 
String s2("hello worl"); 
s2.PushBack('d');
cout << s2.GetStr() << endl; 
String s3("hello worldd");
s3.PopBack();
cout << s3.GetStr() << endl; 
String s4("hello");
s4.Insert(5,'d');
cout << s4.GetStr() << endl; 
String s5("hellod");
s5.Erase(5);
cout << s5.GetStr() << endl; 
String s6("hellolllo");
s6.Erase(5, 4);
cout << s6.GetStr() << endl; 
String s7("he");
s7.Insert(1, "llo");
cout << s7.GetStr() << endl;
}
int main()
{
Test1();
system("pause");
return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值