自己简单实现一下String类,代码如下:
//自己简单实现一下String类
#pragma warning( disable : 4996)
class MyString
{
private:
char*_data;
size_t _len;
void _init_data(const char*s)
{
_data = new char[_len + 1];
memcpy(_data, s, _len);
_data[_len] = '\0';
}
public:
MyString() :_data(NULL), _len(0) { }//default constructor
MyString(const char*p) :_len(strlen(p))//constructor
{
_init_data(p);
//cout << "constructor" << endl;
}
MyString(const MyString&str) :_len(str._len)//copy constructor
{
_init_data(str._data);
}
MyString&operator=(const MyString&str)//copy assignment
{
if (this != &str)
{
if (this->_data)delete[] _data;
_len = str._len;
this->_init_data(str._data);
}
else
{
}
return *this;
}
//C++11
MyString(MyString&&str) noexcept:_data(str._data), _len(str._len)//move constructor 形参是右值引用
{
//noexcept关键字告诉编译器,函数中不会发生异常
str._data = NULL;//避免浅拷贝
str._len = 0;
}
MyString&operator=(MyString&&str)noexcept//move assignment
{
if (this != &str)
{
this->_data = str._data;
str._data = NULL;
this->_len = str._len;
str._len = 0;
}
return *this;
}
~MyString()//destructor
{
delete[] this->_data;
}
char*get()const
{
return this->_data;
}
bool operator==(const MyString&rhs)const
{
return strcmp(this->_data, rhs._data) == 0 ? true : false;
}
bool operator<(const MyString&rhs)const
{
return strcmp(this->_data, rhs._data) < 0 ? true : false;
}
MyString operator+(const MyString&rhs)
{
MyString ret;
ret._len = this->_len + rhs._len;
ret._data = new char[ret._len + 1];
strcpy(ret._data, this->_data);//回顾一下strcpy(dest,src)把从src地址开始且含有null结束符的字符串复制到以dest开始的地址空间
strcat(ret._data, rhs._data);//回顾一下strcat(dest,src)把src所指的字符串添加到dest结尾处(覆盖结尾处的'\0')并添加'\0'
return ret;
}
MyString&operator+=(const MyString&rhs)
{
if (rhs._data == NULL)
return *this;
if (this == &rhs)//如果出现了自己加自己的情况(必须判断这种情况)
{
MyString copy(*this);//调用copy constructor
return *this += copy;//再次调用该函数本身,但是这一次调用不会进入if了
}
this->_len += rhs._len;
char*p_old = this->_data;
this->_data = new char[this->_len + 1];
strcpy(this->_data, p_old);
strcat(this->_data, rhs._data);
delete[] p_old;
return *this;
}
MyString&operator+=(const char&rhs)
{
this->_len += 1;
char*p_old = this->_data;
this->_data = new char[this->_len + 1];
strcpy(this->_data, p_old);
_data[this->_len - 1] = rhs;
_data[this->_len] = '\0';
delete[] p_old;
return *this;
}
char& operator[](const size_t index)
{
if (index < 0 || index >= this->_len)
{
throw exception("越界啦");
}
return this->_data[index];
}
//ostream
friend ostream& operator<< (ostream& out, const MyString &str)//友元函数
//需要把运算符重载函数声明为类的友元函数,这样我们就能不用创建对象而直接调用函数
{
if (str._data != NULL)
{
out << str._data;
}
return out;
}
// istream
friend istream& operator >> (istream& in, MyString& str)//友元函数
{
char tmp[100];// 临时字符串
if (in >> tmp)
{
delete[] str._data;
str._len = strlen(tmp);
str._data = new char[str._len + 1];
strcpy(str._data, tmp);
}
return in;
}
//这里操作符重载只简单地写几个,其他就不写了,不难
bool isEmpty()
{
return this->_len == 0 ? true : false;
}
size_t length()
{
return this->_len;
}
const char*c_str()//将C++的string转化为C的字符串,c_str()生成一个const char *指针
{
return this->_data;
}
MyString&append(const MyString&rhs)
{
*this += rhs;
return *this;
}
MyString substr(size_t pos, const size_t n)//substr返回的是对象,不是引用//s.substr(pos, n)返回一个包含s中从pos开始的n个字符的拷贝
{
if ((pos + n) > this->_len)
throw exception("越界啦");
MyString ret;
ret._len = n;
ret._data = new char[ret._len + 1];
for (size_t i = 0; i < n; i++)
{
ret._data[i] = this->_data[pos + i];//调用[]重载函数
}
ret._data[n] = '\0';
return ret;
}
MyString&erase(size_t pos, size_t n)//erase(pos,n)删除从pos开始的n个字符
{
if (pos >= _len)
{
throw("越界啦");
}
if ((pos + n - 1) >= this->_len)//自动修正功能
{
n = _len - pos;
}
char*p_old = this->_data;
this->_len -= n;//更新_len
this->_data = new char[this->_len + 1];
for (size_t i = 0; i < pos; i++)//p_old数组下标[0,pos-1]
{
this->_data[i] = p_old[i];
}
for (size_t i = pos; i < this->_len; i++)//p_old数组下标[pos+n,pos+_len-1]
{
this->_data[i] = p_old[n + i];
}
this->_data[this->_len] = '\0';
delete[] p_old;
return *this;
}
void swap(MyString&lhs, MyString&rhs)
{
lhs._len ^= rhs._len;
rhs._len ^= lhs._len;
lhs._len ^= rhs._len;
char*temp = lhs._data;
lhs._data = rhs._data;
rhs._data = temp;
}
};
int main()
{
cout << sizeof(MyString) << endl;
MyString str1("Chinese");
cout << (str1.substr(1, 6)).get() << endl;
cout << str1 << endl;
str1 += "123";
cout << str1.get() << endl;
str1.append("456");
cout << str1.get() << endl;
str1.erase(7, 2);
cout << str1 << endl;
cin >> str1;
cout << str1 << endl;
cout << "---------------------------------------------------" << endl;
MyString str2;
str2 = str1;//断点copy assignment
MyString str3(str1);//断点copy constructor
MyString str4(move(str1));//断点move constructor
cout << str1.length() << endl;//这里特别注意,使用move后str1被掏空,失效了,最好不要再去使用str1
cout << "---------------------------------------------------" << endl;
MyString str5;
str5 = MyString("abc");//断点move assignment,因为返回的是一个右值
MyString str6("xyz");
MyString str7("lalala");
cout << str7.get() << endl;
str7 = str6.substr(0, 1);//断点move assignment,因为返回的是一个右值
cout << str7.get() << endl;
cout << "---------------------------------------------------" << endl;
MyString str8 = MyString("aaa");//注意,这里只会调用1次constructor,除此以外不会调用其他任何函数
//这是为什么呢,原因是编译器会自动进行优化,将上面这句话优化为MyString str8("aaa");
system("pause");
return 0;
}