一、简介
C++标准库中包含一个string类,提供了一套封装好的数据以及处理这些数据的函数。为了熟悉这个类的内存管理情况,实现一下自定义的String类,涉及构造函数、复制构造函数、析构函数、重载运算符的操作,主要关注其内部指针的内存的重分配。
二、详解
1、代码实现:
(1)代码String.h:
- #include <iostream>
- using namespace std;
- //自定义String类,系统是string类
- class String
- {
- public:
- String(); //默认构造函数,用于创建空字符串
- ~String(); //析构函数
- String(const char*const cstr); //构造函数,带一个参数用来初始化字符串
- String(const String &rs); //复制构造函数,默认是浅层复制,需重载
- char& operator[](unsigned int length); //重载下标运算符[]
- char operator[](unsigned int length)const; //重载下标运算符[](const版本)
- String &operator=(const String &rs); //重载复制运算符=,用于两个字符串之间的赋值
- String operator+(const String &rs); //重载加法运算符+
- String operator+=(const String &rs); //重载组合运算符+=
- friend ostream &operator<<(ostream &output, const String &str); //重载输出流运算符<<
- friend istream &operator>>(istream &input, String &str); //重载输入流运算符>>
- friend bool operator<(const String&str1,const String &str2); //重载小于运算符<
- friend bool operator>(const String&str1,const String &str2); //重载大于运算符>
- friend bool operator==(const String&str1,const String &str2); //重载等于运算符==
- unsigned int getlen()const; //获取字符串长度
- const char*getstr()const; //获取字符串
- //int operator++(){cout<<"++i\n";tmp++;return tmp;} //int的重载自加运算符
- //int operator++(int){cout<<"i++\n";int tmp=rs;rs++;return tmp;}
- protected:
- private:
- unsigned int len;
- char *str;
- };
(2)代码String.cpp:
- #include <string.h>
- #include "String.h"
- #include <stdio.h>
- //默认构造函数,用于创建空字符串
- String::String()
- {
- cout<<"---String constructor---"<<endl;
- len = 0;
- str = new char[1];
- str[0] = '\0';
- }
- //析构函数
- String::~String()
- {
- //cout<<"---String destructor---"<<endl;
- delete []str;
- len=0;
- }
- //构造函数,带一个参数用来初始化字符串
- String::String(const char*const cstr)
- {
- /*len = strlen(cstr);
- str = new char[len+1];
- for (unsigned int i =0; i < len; i++) {
- str[i] = cstr[i];
- }
- str[len]='\0';*/
- cout<<"---String constructor:char*---"<<endl;
- if (cstr == NULL) {
- len = 0;
- str = new char[1];
- memset(str, 0, len+1);
- if (str == NULL) return;
- }
- else {
- len = strlen(cstr);
- str = new char[len + 1];
- memset(str, 0, len+1);
- if (str == NULL) return;
- strncpy(str, cstr, len);
- }
- }
- //复制构造函数,默认是浅层复制,需重载
- String::String(const String &rs)
- {
- cout<<"---String copy constructor---"<<endl;
- len = rs.getlen();
- str = new char[len + 1];
- for(unsigned int i = 0 ;i < len; i++) {
- str[i] = rs.str[i];
- }
- str[len] = '\0';
- /*len = rs.getlen();
- str = new char[len+1];
- if (str == NULL) return;
- strcpy(str, rs.str);*/
- }
- //重载下标运算符[]
- char&String::operator[](unsigned int length)
- {
- if(length>len) return str[len-1];
- else return str[length];
- }
- //重载下标运算符[](const版本)
- char String::operator[](unsigned int length)const
- {
- //cout<<"String::operator[] const"<<endl;
- if(length>len) return str[len-1];
- else return str[length];
- }
- //重载复制运算符=,用于两个字符串之间的赋值
- String &String::operator=(const String &rs)
- {
- cout<<"String::operator="<<endl;
- if (this == &rs) return *this;
- delete []str;
- len = rs.getlen();
- str = new char[len + 1];
- for(int i = 0; i < len; i++) {
- str[i] = rs[i]; //重载下标运算符[]才可使用
- //str[i] = rs.str[i];
- }
- str[len] = '\0';
- return *this;
- }
- //重载加法运算符+
- String String::operator+(const String &rs)
- {
- /*char *st= new char[len + rs.getlen() + 1];
- memset(st, 0, len + rs.getlen() + 1);
- strcat(st, str);
- strcat(st, rs.str);
- return String(st);*/
- cout<<"String::operator+"<<endl;
- unsigned int total = len + rs.getlen();
- char *tmpstr = new char[total + 1];
- unsigned int i, j;
- for (i = 0; i < len; i++) {
- tmpstr[i] = str[i];
- }
- for( j = 0; j < rs.getlen(); j++, i++) {
- tmpstr[i] = rs[j];
- }
- tmpstr[total] ='\0';
- String st(tmpstr);
- delete tmpstr;
- tmpstr = NULL;
- return st;
- }
- //重载组合运算符+=
- String String::operator+=(const String &rs)
- {
- cout<<"String::operator+="<<endl;
- int total = len + rs.getlen();
- //delete []str;
- char *tmpstr = new char[total + 1];
- unsigned int i,j;
- for(i = 0; i < len; i++) {
- tmpstr[i] = str[i];
- }
- for(j = 0; j < rs.getlen(); j++,i++) {
- tmpstr[i] = rs[j];
- }
- tmpstr[total]='\0';
- delete []str;
- str = new char[total + 1];
- strncpy(str, tmpstr, total + 1);
- return *this;
- /*
- char *temp = str;
- len = len + rs.getlen();
- str = new char[len + 1];
- strcpy(str, temp);
- strcat(_str, rs.getstr());
- delete[] temp;
- return *this;*/
- }
- //重载输出流运算符<<
- ostream &operator<<(ostream &output, const String &str)
- {
- output<<str.str;
- return output;
- }
- //重载输入流运算符>>
- istream &operator>>(istream &input, String &str)
- {
- input>>str.str;
- return input;
- }
- //重载小于运算符<
- bool operator<(const String&str1,const String &str2)
- {
- if(strcmp(str1.str, str2.str) < 0) return 1;
- else return 0;
- }
- //重载大于运算符>
- bool operator>(const String&str1,const String &str2)
- {
- if(strcmp(str1.str, str2.str) > 0) return 1;
- else return 0;
- }
- //重载等于运算符==
- bool operator==(const String&str1,const String &str2)
- {
- if(strcmp(str1.str, str2.str) == 0) return 1;
- else return 0;
- }
- //获取字符串长度
- unsigned int String::getlen()const
- {
- return len;
- }
- //获取字符串
- const char*String::getstr()const
- {
- return str;
- }
- #include <iostream>
- #include <stdio.h>
- #include "String.h"
- using namespace std;
- int main()
- {
- String str1; //默认构造函数
- String str2(NULL); //带参构造函数
- String str3("helloworld"); //带参构造函数
- cout<<"str3="<<str3.getstr()<<endl;
- String str4(str3); //复制构造函数
- //String str4 = str3; //复制构造函数
- cout<<"str4="<<str4.getstr()<<endl;
- const String str5("tai"); //重载下标运算符[](const版本)
- cout<<"str5[0]="<<str5[0]<<endl;
- String str6;
- str6 = str3; //重载复制运算符=
- cout<<"str6="<<str6.getstr()<<endl;
- String str7 = str3 + str5; //重载加法运算符+
- cout<<"str7="<<str7.getstr()<<endl;
- String str8("123");
- str8 += str7; //重载组合运算符+=
- cout<<"str8="<<str8.getstr()<<endl;
- String str9;
- cin>>str9; //重载输入流运算符>>
- cout<<"str9="<<str9<<endl; //重载输出流运算符<<
- String str10("compare String");
- String str11("compare string");
- int comp = str10 > str11;
- cout<< "str10大于str11:" << comp <<endl;
- return 0;
- }