String类实现
- 概述
- 示例
- 开发环境
- 代码
- 运行结果
- 注意
概述
本文主要记录自己实现一个String类中的部分功能。
示例
开发环境
Windows下Visual Studio 2019。
代码
MyString.h
#pragma once
#include <iostream>class MyString{
public:MyString();MyString(char *p);MyString(const char *p);MyString(const MyString& s);MyString(MyString&& s);MyString& operator=(const MyString& s);MyString& operator=(MyString&& s);bool operator<(const MyString &s);bool operator==(const MyString& s);MyString& operator+=(const MyString& s);int getLeng()const;char getIndexCharacter(const int& index);friend std::ostream& operator<<(std::ostream & o,const MyString& s);//友元函数不是类成员函数,可访问私有成员friend std::istream& operator>>(std::istream& i,MyString &s);
private:char* m_pStr;int m_len;
};
MyString.cpp
#include "MyString.h"
#include <string>MyString::MyString():m_pStr(nullptr),m_len(0)
{m_pStr = new char[1];m_pStr[0] = '\0';m_len = 1;
}MyString::MyString(char* p)
{if (p) {int nLen = strlen(p);m_pStr = new char[nLen + 1];memset(m_pStr, 0, nLen + 1);strcpy_s(m_pStr, nLen + 1, p);//目标缓存区的大小m_len = nLen;}else {MyString();}
}MyString::MyString(const char* p)
{if(p){int nLen = strlen(p);m_pStr = new char[nLen +1];memset(m_pStr,0,nLen+1);strcpy_s(m_pStr,nLen+1,p);//目标缓存区的大小m_len = nLen;}else {MyString();}
}MyString::MyString(const MyString& s)
{m_len = s.m_len;m_pStr = new char[m_len+1];memset(m_pStr, 0, m_len + 1);strcpy_s(m_pStr,m_len+1 ,s.m_pStr);m_pStr[m_len] = '\0';
}MyString::MyString(MyString&& s)
{m_len = s.m_len;m_pStr = s.m_pStr;s.m_pStr = nullptr;s.m_len = 0;
}MyString& MyString::operator=(const MyString& s)
{// TODO: 在此处插入 return 语句if (this != &s) {m_len = s.m_len;m_pStr = new char[m_len +1];memset(m_pStr,0,m_len+1);strcpy_s(m_pStr,m_len+1,s.m_pStr);m_pStr[m_len] = '\0';}return *this;
}MyString& MyString::operator=(MyString&& s)
{// TODO: 在此处插入 return 语句if (this != &s) {m_len = s.m_len;m_pStr = s.m_pStr;s.m_len = 0;s.m_pStr = nullptr;}return *this;
}bool MyString::operator<(const MyString& s)
{if (strcmp(m_pStr,s.m_pStr) < 0) {return true;}return false;
}bool MyString::operator==(const MyString& s)
{if (strcmp(m_pStr,s.m_pStr) == 0) {return true;}return false;
}MyString& MyString::operator+=(const MyString& s)
{// TODO: 在此处插入 return 语句m_len += s.m_len;char* pTemp = m_pStr;m_pStr = new char[m_len+1];memset(m_pStr,0,m_len+1);strcpy_s(m_pStr,m_len+1,pTemp);strcat_s(m_pStr, m_len + 1, s.m_pStr);m_pStr[m_len] = '\0';return *this;
}int MyString::getLeng() const
{return m_len;
}char MyString::getIndexCharacter(const int& index)
{if (index >=0 && index < m_len) {return m_pStr[index];}return -1;
}std::ostream& operator<<(std::ostream& o,const MyString& s)
{// TODO: 在此处插入 return 语句o << "字符串的长度:" << s.m_len << ",字符串:" << s.m_pStr;return o;
}std::istream& operator>>(std::istream& i,MyString &s)
{// TODO: 在此处插入 return 语句i >> s.m_len >> s.m_pStr;return i;
}
main.cpp
#include <iostream>
#include "MyString.h"using namespace std;int main(int argc,char *argv[]) {MyString s;cout <<"字符串s: "<< s << endl;const char* p = "future";MyString s0(p);cout << "字符串s0: " << s0 << endl;MyString s1("hello");cout << "字符串s1: " << s1 << endl;char c[15] = "hello world";MyString s2(c);cout << "字符串S2:" << s2 << endl;MyString s3(s2);cout << "字符串s3:" << s3 << endl;MyString s4(move(s0));cout << "字符串s4:" << s4 << endl;MyString s5 = s1;cout << "字符串s5:" << s5 << endl;MyString s6 = move(s2);cout << "字符串s6:" << s6 << endl;if (s5 == s6) {cout << "s5与s6相等!" << endl;}else if(s5 <s6){cout << "s5与s6小于s6!" << endl;}else {cout << "s5与s6大于s6!" << endl;}s5 += s6;cout << "s5追加s6之后: " << s5 << endl;cout << "s5的长度:" <<s5.getLeng()<< endl;cout << "s5的第8个字符:" << s5.getIndexCharacter(11) << endl;return 0;
}
运行结果
注意
- 上面的示例在实现时,输入输出运算符的重载时作为友元函数来声明的,需要访问类对象的成员变量,故而含有两个参数。
一般输出、输出运算符重载都作为类的友元函数。
friend std::ostream& operator<<(std::ostream & o,const MyString& s);//友元函数不是类成员函数,可访问私有成员
friend std::istream& operator>>(std::istream& i,MyString &s);
- 其中构造函数:
MyString(MyString&& s);
为移动拷贝构造函数。
- 下面的赋值运算符重载:
MyString& operator=(MyString&& s);
为移动赋值运算符重载。
参数右值引用传参的时候,使用move()。 可看上述示例调用处。
- 声明为移动构造函数和移动赋值运算符重载的好处 :
避免了深拷贝,只转移所有权,移动之后(即转移所有权之后),原来的对象中的数据被清空,但对象依旧存在。