学习过C++大家对STL应该是都不陌生,C++不学STL那就等于没学,今天是一片简单的string模拟实现,话不多说,直接上代码:
#pragma once
#include <iostream>
#include <cassert>
#include <cstdlib>
#include <string.h>
using namespace std;
namespace cc
{
class string
{
friend istream& operator>>(istream& in,string& s);
public:
//迭代器
typedef char* iterator;
typedef const char* const_iterator;
string(const char *str = "\0")
: _str(new char[strlen(str)+1])
, _capacity(strlen(str))
, _size(_capacity)
{
strcpy(_str,str);
}
string(const string& d)
: _str(nullptr)
{
string tem(d._str);
swap(tem);
}
~string()
{
delete[] _str;
_str=nullptr;
_capacity=_size=0;
}
string& operator=(string d)
{
swap(d);
return *this;
}
iterator begin()
{
return _str;
}
iterator end()
{
return _str+_size;
}
const_iterator begin()const
{
return _str;
}
const_iterator end()const
{
return _str+_size;
}
void swap(string& d)
{
std::swap(_str,d._str);
std::swap(_capacity,d._capacity);
std::swap(_size,d._size);
}
size_t capacity()const
{
return (size_t)_capacity;
}
size_t size()const
{
return (size_t)_size;
}
char& operator[](const int& x)const
{
assert(x<(int)size());
return *(_str+x);
}
char* c_str()const
{
return _str;
}
void resize(size_t n,const char* str="\0")
{
_size=n;
for(size_t i=0;i<_size;i++)
_str[i]=str[i];
}
void reserve(size_t n)
{
if(_str==nullptr)
{
_str=new char[5];
_capacity=4;
_size=4;
}
else if(n>capacity())
{
char *tem=new char[n];
strcpy(tem,_str);
delete[] _str;
_str=tem;
_capacity=strlen(_str);
_size=_capacity;
}
}
//运算符重载
bool operator==(const string& d)const;
bool operator<=(const string& d)const;
bool operator!=(const string& d)const;
//......
private:
char *_str;
int _capacity;
int _size;
//此数组的作用类似于是缓冲区
//char _buf[15];
};
//重载<<不能用友元函数
ostream& operator<<(ostream& out,const string& s)
{
size_t i=0;
for(i=0;i<s.size();i++)
out<<s[i];
return out;
}
//方法一:
// istream& operator>>(istream& in,const string& s)
// {
// char ch;
// ch=in.get();
// //这里最好加上一个缓冲区(缓冲区用数组来代替,目的是提高效率)
// while(ch!=' '&&ch!='\n')
// {
// //s+=ch;
// ch=in.get();
// }
// return in;
// }
//方法二:
istream& operator>>(istream& in,string& s)
{
in>>s._str;
return in;
}
}
功能没有实现全面,但是只是一些简单的功能函数没有实现,主要的都已经实现。现在就说说string模拟实现中的一些关键性问题:
首先就是,string是深拷贝,这个很简单,深浅拷贝在前面已经浅浅的说过一些了,深拷贝其实就是要让他们指向的空间不一样,这样析构的时候就没有错误了。
还有就是,大家一定要注意的是,在重载流插入和流提取的运算符时,个人认为插入既可以用友元函数,也可以自己写,上面有两种方法的代码,而在自己实现的过程中,一定要注意的是,cin其实是忽略空格和换行的,所以此时就要用到的是cin中的一个成员函数。而我写的那个数组其实就是类似于一个缓冲区的东西,类似于减少IO次数,提高效率的作用。而流提取不可以用友元函数,因为string中的打印是有多少打印多少,而不是遇见‘\0’就结束,这个一定要注意。(这里谨记,一定要少用友元函数,因为其破坏了封装)。所以还是建议自己实现,不要用友元函数。
而还要注意的是string中的容量其实是比显示的容量大的,因为还有一个'\0',还有就是,仔细的小伙伴可能看到我私有成员变量中还写了一个数组,这个其实很简单,这个其实也是类似于一个缓冲区,因为每次扩容所付出的代价极大,所以我们也可以定一个数组来充当缓冲区,这样就会好很多。而vs2013,2019等环境下,其实我们可以看到源码,其中就有这个数组来充当缓冲区,所以我们也可以模拟一下。
上面是string的注意事项,如果本篇内容对你们有用的话,希望大家点一下赞,支持一下!!