【C++】使用类来模拟string
文章目录
- 第一步:构建简单的构造函数和析构函数
- 1.1 模拟输出(operator<<)
- 为了避免使用友元:在类外在定义再写一个输出函数:
- 1.2 拷贝构造函数
- 1.3 赋值运算符重载
- 1.4 加法运算符重载
- 1.4.1对象和对象相加
- 1.4.2字符串和对象相加
- 1.5 移动构造函数
- 1.6 移动赋值运算符重载在整个程序执行的过程中,只对堆内存空间new了一次,
- **重点**:
- 重点:
- 完整代码:
第一步:构建简单的构造函数和析构函数
class String
{private:char* str;
public:String(char* p, int){str = p;}//构造函数String(const char* p = NULL) :str(NULL){if (p != NULL)//要传的字符串不为空{//申请堆空间str = new char[strlen(p) + 1];strcpy_s(str, strlen(p) + 1, p);}else{str = new char[1];*str = '\0';}cout << "Create String:" << this << endl;}//析构函数~String(){if (str != NULL){delete[]str;}str = NULL;cout << "Destory String" << this << endl;}
};
1.1 模拟输出(operator<<)
避免友元函数,需要在类外写一个输出函数
ostream& operator<<(ostream& out)const{ //this->strif (str != NULL){out << str; }return out;}
为了避免使用友元:在类外在定义再写一个输出函数:
ostream& operator<<(ostream& out,const String &s)
{ //类外没有this指针,需要在定义一个对象ss << out; //<<调用类中的 s.operator<<() return out;}
int main()
{String s{ "baiU" };cout << s << endl;//直接调用输出运算符,输出对象
}
1.2 拷贝构造函数
String(const String& s){//避免浅拷贝str = new char[strlen(s.str) + 1];;strcpy_s(str, strlen(s.str) + 1, s.str);cout << "copy String" << this << endl;}
int main()
{String s{ "baiU" };String s1(s);
}
1.3 赋值运算符重载
String& operator = (const String& s){if (this != &s){delete[]str;str = new char[strlen(s.str) + 1];strcpy_s(str, strlen(s.str) + 1, s.str);}cout << "operator =" << this << endl;return *this;}
注意点:防止自赋值,防止内存泄漏,防止浅拷贝
int main()
{String s{ "baiU" };String s1(s);String s2{"shiqianyu"};s2 = s;
}
1.4 加法运算符重载
因为返回时要构造一个对象,需要在重载一个构造函数,作为私有成员。
String(char* p, int)//int 占位符{str = p;}
1.4.1对象和对象相加
String operator+(const String& s){int len = strlen(str) + strlen(s.str) + 1;char* p = new char[len];strcpy_s(p, len, str);strcat_s(p,len,s.str);cout << "Object+object" << endl;return String(p, 1);}
1.4.2字符串和对象相加
String operator+(const char* p, const String& s)
{cout << "char* + Object" << endl;return String(p) + s;
}
int main()
{String s{ "baiU" };String s2{"shiqianyu"};s = s + s2;// s2 = "love" + s2;String s3;s3 = fun();return 0;
}
1.5 移动构造函数
String(String&&s){cout << "move construct:" << this<<endl;str = s.str;s.str = NULL;}
1.6 移动赋值运算符重载在整个程序执行的过程中,只对堆内存空间new了一次,
String fun()
{String s2("yangyu");return s2;
}
```cppint main()
{String s1; //调用默认构造申请对象空间s1 = fun();return 0;
}
String s1;
调用构造函数申请对象空间
2. String s2{yangyu};
调用构造函数,申请空间,创建对象,并对对象进行初始化。
3. return s2
调用移动构造函数,创建将亡值对象,并让将亡值对象指向s2.(str = s.str;
)。并把s2中str置为空(s.str = NULL;
)
4. 析构s2
5. s1 = fun() 调用Release()完成数据交换。 s.str = Release(s.str);·
重点:
- 首先s2调用构造函数完成对str的初始化,也就是s2指向为字符串“baiU”开辟的堆空间。
- return s2时,返回调用点处(调用的是移动构造函数)创建将亡值对象,指向 s2申请的空间,
- s2析构。
- 将亡值移动赋值给s1过程。
char* Release(char* p){char* old = str;str = p;return old;}
重点:
Release()函数实现了资源的交换,让s1指向s2申请的空间,将亡值指向s1申请的空间,函数结束。将亡值值被析构,s1成功拿到了原s2的资源,
//优先调用String& operator = (String&&s){if (this != &s){s.str = Release(s.str); //将str = s.str 并将str原本的值释放掉。}cout << "operator =&&" << this << endl;return *this;}
完整代码:
class String
{private:char* str;
public:String(char* p, int){str = p;}//构造函数String(const char* p = NULL) :str(NULL){if (p != NULL)//要传的字符串不为空{//申请堆空间str = new char[strlen(p) + 1];strcpy_s(str, strlen(p) + 1, p);}else{str = new char[1];*str = '\0';}cout << "Create String:" << this << endl;}//拷贝构造函数String(const String& s){//避免浅拷贝str = new char[strlen(s.str) + 1];;strcpy_s(str, strlen(s.str) + 1, s.str);cout << "copy String" << this << endl;}//移动构造函数String(String&&s){cout << "move construct:" << this<<endl;str = s.str;s.str = NULL;}//析构函数~String(){if (str != NULL){delete[]str;}str = NULL;cout << "Destory String" << this << endl;}//避免友元函数,需要在类外写一个输出函数ostream& operator<<(ostream& out)const{ //this->strif (str != NULL){out << str; }return out;}//赋值运算符重载String& operator = (const String& s){if (this != &s){delete[]str;str = new char[strlen(s.str) + 1];strcpy_s(str, strlen(s.str) + 1, s.str);}cout << "operator =" << this << endl;return *this;}char* Release(char* p){char* old = str;str = p;return old;}//优先调用String& operator = (String&&s){if (this != &s){s.str = Release(s.str); //将str = s.str 并将str原本的值释放掉。}cout << "operator =&&" << this << endl;return *this;}//加法运算符重载//对象和对象相加String operator+(const String& s){int len = strlen(str) + strlen(s.str) + 1;char* p = new char[len];strcpy_s(p, len, str);strcat_s(p,len,s.str);cout << "Object+object" << endl;return String(p, 1);}};
String fun()
{String s2("yangyu");return s2;
}ostream& operator<<(ostream& out,const String &s)
{ //类外没有this指针,需要在定义一个对象ss << out; //<<调用类中的 s.operator<<() return out;}
String operator+(const char* p, const String& s)
{cout << "char* + Object" << endl;return String(p) + s;
}
int main()
{// String s{ "baiU" };// cout << s << endl;//直接调用输出运算符,输出对象s// String s1(s);// String s2{"shiqianyu"};// s2 = s;s = s + s2;// s2 = "love" + s2;String s3;s3 = fun();return 0;
}
【C++】使用类来模拟string相关推荐
- 内存分布malloc/calloc/realloc/free/new/delete、内存泄露、String模板、浅拷贝与深拷贝以及模拟string类的实现
内存分布 一.C语言中的动态内存管理方式:malloc/calloc/realloc和free 1.malloc: 从堆上获得指定字节的内存空间,函数声明:void *malloc (int n); ...
- String类的模拟实现
目录: 一.经典String类的问题 1,浅拷贝 2,深拷贝 二.现代写法版的string类 三.传统String类的模拟实现 1.迭代器 2.operator[] 3.size() 4.c_str( ...
- C++关于string类的模拟实现
文章目录 一.string类的模拟实现 1.成员变量 2.构造函数 (1)无参构造函数 (2)有参构造函数 3.c_str函数 4.operator[] 5.深浅拷贝问题 (1)浅拷贝 (2)深拷贝 ...
- Java黑皮书课后题第10章:**10.7(游戏:ATM机)使用编程练习题9.7中创建的Account类来模拟一台ATM级
**10.7(游戏:ATM机)使用编程练习题9.7中创建的Account类来模拟一台ATM级 题目 程序 代码 Test7.java Test7_Account.java 运行示例 题目 程序 Tes ...
- java定义计算机类并模拟其操作
java定义计算机类并模拟其操作 /*** 定义计算机类并模拟其操作*/ public class Computer {//成员变量private String cpu = "Intel&q ...
- java面向对象第一课,定义类,模拟人的行为:吃饭工作休息
java面向对象第一课,定义类,模拟人的行为:吃饭工作休息 /*** 定义类,模拟人的行为:吃饭工作休息*/ public class Person {//静态特征:成员变量 属性 fieldStri ...
- 重学JavaSE 第11章 : 常用类API、String、日期API、比较器、BigDecimal、System等
文章目录 一.字符串相关的类 1.1.String类的概述 1.2.理解String的不可变性 1.3.String不同实例化方式的对比 1.4.String不同拼接操作的对比 1.4.1.Strin ...
- 【蓝桥】第十一届软件类校内模拟赛(一)
前言 本题解为第十一届软件类校内模拟赛个人题解,但非官方满分题解,因此,可能存在下列问题 题意理解错误,导致答案错误. 代码中存在一些问题,导致答案错误. 算法复杂度的分析有误,导致不能在规定时间内得 ...
- Java储蓄账户类及测试类,模拟存款
老师布置了一个实验题:编写储蓄账户类及测试类,模拟存款,参考以下运行方式: 1.新开5个储蓄账户,各储蓄账户的编号.户名在新开储蓄账户时初始化,假设每位用户新开储蓄账户时都存入了一笔钱. 2.提示用户 ...
- java模拟使用接口,关于java:模拟一个类与模拟它的接口
对于单元测试,我需要模拟几个依赖项.依赖项之一是实现接口的类: public class DataAccessImpl implements DataAccess { ... } 我需要设置一个这个类 ...
最新文章
- ​超大规模时空数据的分布式存储与应用
- 检查字符串是否包含数字
- element ui分页怎么做_element ui里面table分页,页数从0开始的怎么做?
- Android震动vibrator系统开发全过程
- python tqdm自定义更新进度条
- arcgis api for javascript中使用proxy.jsp
- 【面试】iOS 开发面试题(二)
- python的函数调用_三个案例带你了解python回调函数
- html条纹填充色,HTML5/Canvas 上传图片的彩色斑马条纹遮罩效果
- canvas学习笔记-贝塞尔曲线
- qfileinfolist 取中间_公司起名:网络公司名字起名寓意如何取寓意成功的网络公司名字...
- steam一键授权工具_超实用小工具!一键将PC其它平台的游戏导入Steam
- 基于ThinkPHP5+MySQL的超市进销存管理系统
- 时不变线性系统和时变线性系统方程的对角化
- 弹性均质圆环法计算过程_盾构隧道衬砌管片计算方法的比较
- 微型计算机偏移地址,请高手讲解一下在微机原理里面,偏移地址,段地址,实体地址之间的关系!配合图解更好,谢谢!...
- 计算机节能+关闭硬盘,优化三:CPU节能关闭_固态硬盘-中关村在线
- Programming Rust Fast, Safe Systems Development(译) 引用(第五章 完)
- 职场人士需了解:职场文件删除了三种恢复方法
- win10,win11后在cmd命令行输入python自动调用微软应用商店