织梦禁止网站右击,国外好用的免费服务器,专门做婚姻法的网站,唐山的做网站的企业⭐本篇重点#xff1a;string类的模拟#xff0c;自己实现一个简单的string类 ⭐本篇代码#xff1a;c学习/05.string类的学习 橘子真甜/c-learning-of-yzc - 码云 - 开源中国 (gitee.com) 目录 一. 经典string类的模拟
1.1 深浅拷贝问题 1.2 使用深拷贝完成经典string类的… ⭐本篇重点string类的模拟自己实现一个简单的string类 ⭐本篇代码c学习/05.string类的学习 · 橘子真甜/c-learning-of-yzc - 码云 - 开源中国 (gitee.com) 目录 一. 经典string类的模拟
1.1 深浅拷贝问题 1.2 使用深拷贝完成经典string类的模拟
a size函数
b 拷贝构造函数 c 赋值运算符重载
d operator[]重载
二. 现代写法的string类模拟
2.1 拷贝构造函数 2.2 赋值运算符重载
三. 下篇文章STL中vector的使用 一. 经典string类的模拟 实现一个简单的string类主要是实现string类的构造函数析构函数拷贝构造函数赋值运算符重载。这个过程需要我们首先理解深浅拷贝的问题。
1.1 深浅拷贝问题 浅拷贝问题如果我们初始化一个对象的时候只是简单的将另一个对象的值赋值给这个对象。比如我们在堆上申请的空间。当我们销毁这两个对象的时候由于它们指向同一个空间这个空间就会被销毁两次。程序就会崩溃。
测试代码
#define _CRT_SECURE_NO_WARNINGS 1
#include iostream
#include string
using namespace std;namespace yzc
{class string{public:string(const char* str ):_str(new char[strlen(str) 1]){cout 调用构造函数 endl;strcpy(_str, str);}//拷贝构造string(const string str){*this str;}~string(){cout 调用析构函数 endl;delete[] _str;}void print(){cout _str endl;}private:char* _str;};
}int main()
{yzc::string s1 123456;yzc::string s2 abcdef;s1.print();s2.print();return 0;
}没有调用拷贝构造函数可以正常输出。
运行结果如下 如果我们使用拷贝构造函数
int main()
{yzc::string s1 123456;yzc::string s2(s1);return 0;
}分析代码可知由于浅拷贝问题。输出一次调用构造函数和两次析构函数后程序崩溃
只有使用深拷贝我们在拷贝构造函数里面重新申请一份空间然后重新全部复制才行。 1.2 使用深拷贝完成经典string类的模拟
a size函数 为了完成深拷贝我们需要定义一个size函数用于求_str的长度。加上const因为函数内部并不会更改任何值 int size()const{return strlen(_str);}
b 拷贝构造函数
与构造函数类似我们重新开辟一份空间然后使用strcpy进行拷贝
//拷贝构造,使用深拷贝完成拷贝string(const string s):_str(new char[s.size()]){strcpy(_str, s._str);}
测试代码
#define _CRT_SECURE_NO_WARNINGS 1
#include iostream
#include string
using namespace std;namespace yzc
{class string{public:string(const char* str ):_str(new char[strlen(str) 1]) //由于C语言字符串后面都带\0,需要加上1{strcpy(_str, str);}拷贝构造//string(const string str)//{// *this str;//}//拷贝构造,使用深拷贝完成拷贝string(const string s):_str(new char[s.size() 1]) //一定要注意要加1否则会越界访问{strcpy(_str, s._str);}~string(){delete[] _str;_str nullptr;}int size()const{return strlen(_str);}void print(){cout _str endl;}private:char* _str;};
}int main()
{yzc::string s1 123456;yzc::string s2(s1);s1.print();s2.print();return 0;
}
测试结果 c 赋值运算符重载
与拷贝构造函数一样要注意深浅拷贝的问题 //赋值运算符重载string operator(const string s){if (this ! s)//地址不同才进行赋值{delete[] _str; //释放原地址空间防止内存泄漏//定义中间变量tmp用于拷贝char* tmp new char[s.size() 1]; //注意要 1strcpy(tmp, s._str);_str tmp;}return *this; //返回当前对象为了支持 a b c} 测试主函数代码如下
int main()
{yzc::string s1 123456;yzc::string s2 abcdef;yzc::string s3 s1;yzc::string s4;s4 s2;s3.print();s4.print();return 0;
}
测试结果 d operator[]重载
我们还能重载[]这个操作符方便我们遍历整个字符串
直接输入i返回_str[i]即可注意const char operator[](size_t i){assert(i size());return _str[i];}const char operator[](size_t i)const{assert(i size());return _str[i];}
测试代码
int main()
{yzc::string s1 159753468244;for (int i 0; i s1.size(); i){cout s1[i] ;}cout endl;return 0;
}运行结果 二. 现代写法的string类模拟
2.1 拷贝构造函数 为了提高代码的复用我们在拷贝构造函数中使用构造函数去构造一个对象然后交换当前对象和这个对象。
代码如下 //现代版写法string(const string s):_str(nullptr){string strTmp(s._str); //使用构造函数将s._str构造一个tmpswap(_str, strTmp._str);//交换_str和tmp}
交换后strTmp由于是局部变量就直接被销毁了 而我们创建的对象被保留 2.2 赋值运算符重载
我们使用传值方法传参交换_str后我们成功创建的对象。且不会影响传入的对象
//现代版写法string operator(string s) //不使用引用传参而是传值{swap(_str, s._str);return *this;}
测试代码
#define _CRT_SECURE_NO_WARNINGS 1
#include iostream
#include assert.h
using namespace std;namespace yzc
{class string{public:string(const char* str ):_str(new char[strlen(str) 1]) //由于C语言字符串后面都带\0,需要加上1{strcpy(_str, str);}拷贝构造,使用深拷贝完成拷贝//string(const string s)// :_str(new char[s.size() 1]) //注意要加1//{// strcpy(_str, s._str);//}//现代版写法string(const string s):_str(nullptr){string strTmp(s._str); //使用构造函数将s._str构造一个tmpswap(_str, strTmp._str);//交换_str和tmp}赋值运算符重载//string operator(const string s)//{// if (this ! s)//地址不同才进行赋值// {// delete[] _str; //释放原地址空间防止内存泄漏// //定义中间变量tmp用于拷贝// char* tmp new char[s.size() 1];// strcpy(tmp, s._str);// _str tmp;// // }// return *this; //返回当前对象为了支持 a b c//}//现代版写法string operator(string s) //不使用引用传参而是传值{swap(_str, s._str);return *this;}~string(){delete[] _str;_str nullptr;}size_t size()const{return strlen(_str);}void print(){cout _str endl;}private:char* _str;};
}int main()
{yzc::string s1 123456;yzc::string s2(s1);yzc::string s3 s1;s1.print();s2.print();s3.print();return 0;
}
运行结果 三. 下篇文章STL中vector的使用