C++如何实现MyString(C++,mystring,开发技术)

时间:2024-05-05 13:17:23 作者 : 石家庄SEO 分类 : 开发技术
  • TAG :

MyString的构造、析构、拷贝构造、赋值运算

classString{ char*str;public: String(constchar*p=NULL):str(NULL) { if(p!=NULL) { str=newchar[strlen(p)+1];//strlen()计算至'\0'截至的字符数 strcpy(str,p); } else { str=newchar[1];//额外提供一个空间 *str='\0'; } } ~String() { if(str!=NULL) { delete[]str; } str=NULL; } //ostream&operator<<(constString*constthis,ostream&out) ostream&operator<<(ostream&out)const//重载插入操作符 { if(str!=NULL) { out<<str; } returnout; } String(constString&s):str(NULL) { //str=s.str;浅拷贝是同一个空间,会造成一个空间释放两次 //深拷贝 str=newchar[strlen(s.str)+1]; strcpy(str,s.str); } String&operator=(constString&s) { if(this!=&s) { delete[]str; str=newchar[strlen(s.str)+1] strcpy(str,s.str); } return*this; }};ostream&operator<<(ostream&out,constString&s){ s<<out; //s.operator<<(cout); //operator<<(&s1,cout); returnout;}intmain(){ Strings1("123"); s1<<cout; //s1.operator<<(cout); //operator<<(&s1,cout); cout<<s1<<endl; //operator<<(cout,s1);}

前面之所以对空指针构建对象提供一个空间的原因:使其在赋值重载中只有指向堆区一种情况进行处理

C++如何实现MyString

通过此方式进行等号运算符重载,然后调动拷贝构造对s2进行重写构造

C++如何实现MyString

输出流重写

classString{ char*str;public: String(constchar*p=NULL):str(NULL) { if(p!=NULL) { str=newchar[strlen(p)+1]; strcpy(str,p); } else { str=newchar[1];//额外提供一个空间 *str='\0'; } } ~String() { if(str!=NULL) { delete[]str; } str=NULL; } //ostream&operator<<(constString*constthis,ostream&out) ostream&operator<<(ostream&out)const//重载插入操作符 { if(str!=NULL) { out<<str; } returnout; }};intmain(){ Strings1("123"); s1<<cout; //s1.operator<<(cout); //operator<<(&s1,cout);}

在这里通过改写前的代码 operator<<(&s1,cout); 不难看出,将cout初始化out,随后将this.str输出至out

ostream& operator<<(ostream& out)const
此处只能使用引用,因为cout在ostream类中进行转移,该类将拷贝构造函数定义为保护访问属性,无法使用cout初始化out,继而只能使用引用;同样若我们不想使用实参去初始化形参,可以将拷贝构造函数定义为私有或保护类型

若希望输出符合cout << s1 << endl;此种形式,需要再写一个全局函数

classString{ char*str;public: String(constchar*p=NULL):str(NULL) { if(p!=NULL) { str=newchar[strlen(p)+1]; strcpy(str,p); } else { str=newchar[1];//额外提供一个空间 *str='\0'; } } ~String() { if(str!=NULL) { delete[]str; } str=NULL; } //ostream&operator<<(constString*constthis,ostream&out) ostream&operator<<(ostream&out)const//重载插入操作符 { if(str!=NULL) { out<<str; } returnout; }};ostream&operator<<(ostream&out,constString&s){ s<<out; //s.operator<<(cout); //operator<<(&s1,cout); returnout;}intmain(){ Strings1("123"); s1<<cout; //s1.operator<<(cout); //operator<<(&s1,cout); cout<<s1<<endl; //operator<<(cout,s1);}

通过此种形式进行翻转,继而达到符合 cout << s1 << endl; 的形式

MyString加号运算符重载

intmain(){ Strings1("123"); Strings2("456"); Strings3; s3=s1+s2; S3=s1+"789"; s3="789"+s1;}

分别写三个加号运算符重载,来对应上面的三个情况(类+类、类+字符串、字符串+类)

 Stringoperator+(constString&s)const { char*p=newchar(strlen(this->str)+strlen(s.str)+1); strcpy(p,this->str); strcat(p,s.str); returnString(p); }

第一个为成员函数,但是存在内存泄漏,需要进行下面的步骤

C++如何实现MyString

在私有成员变量中,创建一个新的构造函数,直接将p给到str,而没有创建新的空间;并且在加号运算符重载进行修改使其调用私有的构造函数

private: String(char*p,int)//两个参数与公有构造区分 { str=p; }public: Stringoperator+(constString&s)const { char*p=newchar(strlen(this->str)+strlen(s.str)+1); strcpy(p,this->str); strcat(p,s.str); returnString(p,1); }

这样就解决了原本内存泄漏的问题
接下来完成剩余两个等号运算符重载

Stringoperator+(constchar*s)const{ char*p=newchar(strlen(this->str)+strlen(s)+1); strcpy(p,this->str); strcat(p,s); returnString(p,1); //return*this+String(s) //上面的方式更方便,但是会构造两个临时对象}

此处需要写在类外,并且需要类内添加友元函数

friend String operator+(const char* t, const String s);

Stringoperator+(constchar*t,constStrings){ char*p=newchar(strlen(s.str)+strlen(t)+1); strcpy(p,s.str); strcat(p,t); returnString(p,1); //returnString(p)+s;与上面同理,并且不需要友元函数}

讨论一个衍生问题

classString{private: char*str;public: String(constchar*p=NULL):str(NULL) { if(p!=NULL) { str=newchar[strlen(p)+1]; strcpy(str,p); } else { str=newchar[1];//额外提供一个空间 *str='\0'; } } ~String() { if(str!=NULL) { delete[]str; } str=NULL; } String(constString&s) { //str=s.str;浅拷贝是同一个空间,会造成一个空间释放两次 //深拷贝 str=newchar[strlen(s.str)]; strcpy(str,s.str); } String&operator=(constString&s) { if(this!=&s) { delete[]str; str=newchar[strlen(s.str)]; strcpy(str,s.str); } return*this; }};Stringfun(){ Strings2("456"); returns2;}intmain(){ Strings1; s1=fun(); return0;}

讨论此程序执行的过程总共创建了多少个对象:

C++如何实现MyString

主函数运行首先开辟main函数栈帧,创建s1对象,默认构造只有大小为一的空间存放“\0”;之后执行fun()函数,分配fun栈帧,然后创建s2对象,创建一个堆区,str指向堆区空间;并且将按值返回,需要构建一个临时对象(将亡值);

将亡值概念:表达式过程中所产生的不具有名字的一个实体,叫做将亡值;将亡值的生存期仅在表达式的调用过程中,表达式调用结束,将亡值就会结束

构建临时对象调用拷贝构造,fun函数结束,s2生存期结束,调动析构函数;首先释放s2调用资源,再归还s2空间;回到主函数,把将亡值赋值给s1调用赋值语句,接着调用将亡值的析构函数进行释放

这个过程中总共创建了三个对象,分别是s1、s2、将亡值对象

那么如果我们对fun以引用进行返回

String&fun(){ Strings2("456"); returns2;}intmain(){ Strings1; s1=fun(); return0;}

当以引用返回,就不会返回一个s2的备份,从引用底层来看会返回s2的地址;这样会从一个已死亡对象来获取数据,继而会得到随机值

C++如何实现MyString

 </div> <div class="zixun-tj-product adv-bottom"></div> </div> </div> <div class="prve-next-news">
本文:C++如何实现MyString的详细内容,希望对您有所帮助,信息来源于网络。
上一篇:初学java开发用哪些工具好下一篇:

17 人围观 / 0 条评论 ↓快速评论↓

(必须)

(必须,保密)

阿狸1 阿狸2 阿狸3 阿狸4 阿狸5 阿狸6 阿狸7 阿狸8 阿狸9 阿狸10 阿狸11 阿狸12 阿狸13 阿狸14 阿狸15 阿狸16 阿狸17 阿狸18