自实现string类的功能

来源:互联网 发布:金蝶是什么软件 编辑:程序博客网 时间:2024/05/22 00:16

自实现string类的功能


主函数

#include "stdafx.h"#include <iostream>using namespace std;#include "String.h"int _tmain(int argc, _TCHAR* argv[]){String s;cout << s.c_str() << endl;String s1("china");cout << s1.c_str() << endl;String s2 = "china"; //等价于 String sss("china");cout << s2.c_str() << endl;String s3(s2);//拷贝行为 s2进行深拷贝得到s3 用一个对象产生另一个对象cout << s3.c_str() << endl;String s4 = s2;  //相当于深拷贝 String s4(s2); 本质也是拷贝构造 //用已有的一个对象 完成一个对象从无到有的创建cout << s4.c_str() << endl;String s5; //先创建了一个空串s5 = s2; //等价于 s5.operator=(s2); 相当于函数的调用cout << s5.c_str() << endl;String s6;s6 = s5 = s2;  //s6.operator=(s5.operator=(s2));cout << s6.c_str() << endl;String x = "abc";String y = "def";String z = x + y;cout << z.c_str() << endl;if (x == y)cout << "x=y" << endl;else if (x > y)cout << "x>y" << endl;elsecout << "x<y" << endl;x[1] = '@';cout << x.c_str() << endl;cout << x.at(1) << endl;cout << "======================================" << endl;String a = "aa";String b = "bb";String c = "cc";(a = b) = c;//赋值运算符重载返回类型为 & 输出的结果:a=cc b=bb c=cc//赋值运算符重载返回类型为 对象 输出的结果:a=bb b=bb c=cc//原因查看后面注释或者 返回栈上的引用或对象 的文章cout << a.c_str() << endl;cout << b.c_str() << endl;cout << c.c_str() << endl;return 0;}

String.h(大写的String,非系统string)

#pragma once#include <iostream>using namespace std;class String{public://String();String(const char* str=NULL);//只读字符串类型为const char*类型 不能修改String(const String & another);  //拷贝构造器~String(); //析构器String& operator=(const String &another);//赋值运算符的重载 赋值返回=左边的引用String operator+(const String &another); //求和产生的是新对象 返回的是新对象的值bool operator>(const String &another);bool operator<(const String &another);bool operator==(const String &another);char& operator[](int idx);char at(int idx);char* c_str();//返回数据成员_strprivate:char* _str; //String类型中存在指针};

String.cpp(大写的String,非系统string)

#include "String.h"#include <string.h>//构造器String::String(const char* str){if (str == NULL) //判断是否是默认的空串{_str = new char[1]; //定义成[]是为了在析构器中delete可以和[len+1]一起delete*_str = '\0'; //生成一个空串}else{int len = strlen(str);_str = new char[len + 1]; //注意len的长度是没有\0的长度 所以申请空间时要+1strcpy(_str, str);}}#if 0----拷贝构造器:1.格式  A(const A &another)2.若不提供 系统会提供默认 一旦自定义 系统不再提供默认3.系统提供的默认 是一种等位拷贝 也就是浅拷贝4.浅拷贝会导致 内存的重析构 doublefree 有些情况下(含有堆空间的时候) 要自实现拷贝构造#endifString::String(const String & another){//_str = another._str;等位拷贝 //此处 another可以访问private的_str 是因为同类对象间无隐私//等位拷贝在处理对象中含有在堆上申请的空间时 //俩个对象会指向同一个区域 在析构时会析构俩次int len = strlen(another._str);_str = new char[len + 1];strcpy(_str, another._str);}//析构器String::~String(){delete[]_str;}#if 0----赋值运算符重载:用一个己有对象,给另外一个己有对象赋值。两个对象均己创建结束后,发生的赋值行为1.编译器提供默认 也是一种等位赋值(本质也是等位拷贝) 一旦自定义系统不再提供默认2.默认赋值运算符重载也是一种等位赋值 浅赋值3.浅赋值会导致两三问题(1)自身内存泄漏(2)内存发生重析构(3)自赋值出错----为什么赋值运算符(=)返回的类型为引用(&)而不是对象:因为赋值这个行为,相当于=左边的对象调用重载函数将右值赋给左值,并返回左值的引用。之所以可以在栈上 返回引用 是因为调用过程中,=左边的对象并没有消失,返回引用不会出错。而且,如果要完成(a=b)=c 这种行为,只有返回引用才能做到。因为首先b对a进行赋值,也就是(a=b),这个式子完成后返回的是a的引用,再将c的值赋值给a的引用,从而可以改变a的值使a=c。如果(a=b)返回类型为对象,存储它的只是一个临时变量,也就是将c的值赋给这个临时变量,并不会改变原有a的值,临时变量也会很快的消失。相当于你只改变了它的替身的值,并没有改变它的真身。所以返回类型要为引用(&).#endifString& String::operator=(const String &another){if (this == &another) //首先判断是否是自赋值return *this;delete[]this->_str; //先把自己释放掉 也就是开始创建的空串 不然的话 //以后指向关系发生改变就没机会释放 造成内存泄漏int len = strlen(another._str);this->_str = new char[len + 1];strcpy(this->_str, another._str);return *this;}#if 0----加号运算符重载----为什么加号运算符(+)重载返回类型为一个对象而不是引用(&):因为加法是产生一个新数据,如x+y 它不会改变x和y的值,可以理解为x调用加号重载函数,使x的值和y的值加到一起,但返回的对象不是x也不是y。而是一个新对象,这个新对象是在栈上临时产生的,它不是这个函数的调用者,它在函数结束后就会消失,如果此时再返回它的引用,也不会得到它的内容,也就是它的真身已经不存在了。这时就必须要返回它的一个替身,这个替身会在栈上新开辟一段空间存放内容,本质上是在重载函数结束后,还能维持一段时间的临时变量。也就是现在x+y这个式子的值。直到z来接受这个临时变量,也就是z=x+y,注意z一定是在等号左边的,这时这个替身,也就是临时变量x+y的值,很快就会消失不见了,但已经完成了所要实现的功能,所以加号重载函数要返回一个对象。#endif String String::operator+(const String &another){String tmp; //新生成一个对象delete[] tmp._str;   //把开始的""清除掉int len = strlen(this->_str);len += strlen(another._str); tmp._str = new char[len + 1];memset(tmp._str, 0, len + 1);  //必须进行清0操作 因为新申请空间内容未知 strcat后会出现未知内容strcat(tmp._str, this->_str);strcat(tmp._str, another._str);//strcpy(tmp._str, strcat(this->_str, another._str));//不能用这个方法 因为this中的_str和another中的_str的//空间大小都是根据自身长度分配的//没有多余的空间来strcat 而tmp的_str//有足够的空间大小来strcpy或strcatreturn tmp;}bool String::operator>(const String &another){if (strcmp(this->_str, another._str) > 0)return true;elsereturn false;}bool String::operator<(const String &another){if (strcmp(this->_str, another._str) < 0)return true;elsereturn false;}bool String::operator==(const String &another){if (strcmp(this->_str, another._str) == 0)return true;elsereturn false;}//之所以返回值为char& 类型是因为可以根据引用类型对原值进行改变 //如果为char类型则不能对原值进行更改char& String::operator[](int idx) {return this->_str[idx]; //x[idx]; x.operator[](int idx)}char String::at(int idx) //at函数不能更改内容 所以返回为char{return this->_str[idx];}char* String::c_str(){return _str;}




原创粉丝点击