1.前言

  最近看了下《C++Primer》,觉得受益匪浅。不过纸上得来终觉浅,觉知此事须躬行。今天看了类类型,书中简单实现了String类,自己以前也学过C++,不过说来惭愧,以前都是用C来写程序,学的C++基本都忘记了,也说明自己以前对C++的理解不够深入。基于这些,觉得有必要动手来写写C++的一些程序了,毕竟C++有很多的功能是C所不具备的。正好看了课本中String类的简单实现,而且string类在C++中的使用频率也很高,了解其内部的实现是很有必要的。所以今天打算写个string类,就当做练手吧。

2.String类的设计

  写类首先是定义类的名字,我们实现的string就叫String吧,以防和标准库中的string类冲突。其次是类中的内部数据,既然是字符串类,必须要把字符串类所代表的字符串保存起来,所以必须定义一个存放这些字符的字符数组或者一个指向字符数组的指针。我是用后者实现,因为这样更为的灵活,不会因为提前定义数组的大小而限制了能存放到数组中的字符个数。为了方便,可以定义字符串的长度,当然也可以不定义,可以在字符数组的末尾存放0来表示字符串的结束,不过每次得到字符串的长度比较麻烦。最后是类对外的接口,根据我们平时使用string类的情况,我们一般会用到接口size(), c_str(),还有就是+,=,>>,<<,+=,[],==等操作符。

  根据前面的分析,可以得到我们要设计的String类中的成员如下所示:

 class String
{
public:
String();
String(const char *);
String(const String &);
String(String &&); //新加的move构造函数 ~String(); String& operator=(const char *);
String& operator=(const String &); bool operator==(const char *);
bool operator==(const String &); char &operator[](int); String operator+(const char *);
String operator+(const char);
String operator+(const String &); String &operator +=(const char *);
String &operator +=(const char);
String &operator +=(const String &); int size(){return _size;}
char *c_str(){return _string;} friend istream &operator>>(istream &cin, String &str);
private:
int _size;
char *_string;
};

3.String类的主要实现

  我们先来说一下构造函数的实现。由于我想实现的String类中存放字符的数组大小是可以根据实际需要存放字符的个数来动态调整的(这样对于存放字符的个数就没有限制,除非内存不够用了),所以必须根据实际存放的字符个数来动态的申请内存空间,代码可以用如下的方式实现:

 String::String(const char *str)
{
if (!str)
{
_size = ;
_string = NULL;
}
else
{
_size = strlen(str);
_string = new char[_size + ];
strcpy(_string, str);
_string[_size] = ;
}
}

  由于构造函数动态申请了内存,所以必须定义析构函数来释放我们申请的内存空间。

 String::~String()
{
if (_string)
delete _string; cout << "~String() call" << endl;
}

  同样,由于我们每个String类都会动态的申请内存空间,所以必须定义拷贝构造函数,否则默认的拷贝构造函数会导致多个String对象共享相同内存空间的问题(深拷贝与浅拷贝的的问题)。代码和前面的构造函数差不多。

 String::String(const String &str)
{
if (!str._size)
{
_size = ;
_string = NULL;
}
else
{
_size = str._size;
_string = new char[_size + ];
strcpy(_string, str._string);
_string[_size] = ;
} }

 

  其它的函数就是对+,=,+=操作符的重载,原理都是一样的,需要重新分配内存空间来适应新的字符串个数的需求,不同的是+的返回类型不需要使用引用。具体代码如下(用+=实现的):

String String::operator+(const String &str)
{
assert(_string && str._string); String str_temp(*this); str_temp += str;
return std::move(str_temp);
}

  由于函数+会返回对象,编译器会默认产生一个临时的对象,这个对象完全是返回对象的拷贝,而返回对象马上就会析构掉,所以如果我们能把返回对象中的字符数组地址拷贝到临时对象中,那么临时对象就可以不用再申请内存了,这样可以提供效率。所以这里我实现了一个move函数( tangzhnju的提醒):

String::String(String && str)
{
_size = str._size;
_string = str._string;
str._string = NULL;
}

  还有我们经常用的是直接对string类进行输出,所以我们必须重载<<,>>操作符,由于输入需要用到String类中的私有成员变量_string,所以应该把输入函数设置为String类的友元函数。而输出可以通过调用c_str函数获得字符数组地址来输出。

istream &operator>>(istream &cin, String &str)
{
const int limit_string_size = ; str._string = new char[limit_string_size]; cin >> setw(limit_string_size) >> str._string;
str._size = strlen(str._string);
return cin;
} ostream &operator<<(ostream &cout, String &str)
{
return cout << str.c_str();
}

  编写这个String类遇到了两个小的问题,一个就是在写+=操作符重载函数的时候,忘记在函数的前面写String::,导致编译器总是包各种莫名的错误,什么参数不对,不能访问内部成员,这个问题完全是自己粗心导致的。另一个问题就是写+操作符重载函数,开始写+函数的时候直接修改了当前的String对象,后来测试发现这是有问题的,因为+应该重新返回一个新的String对象,这个新String对象是当前String对象与传入参数的字符串的和,这个问题完全是自己没有想清楚+与+=的区别,+=才是要修改当前String对象的。

附加:String类实现代码

自己实现简单的string类的更多相关文章

  1. 实现简单的string类

    摘要 实现了一个string类,包括基本的构造.赋值.判断.大小写等. String API Constructors string(); string(const char& ch); st ...

  2. 一个简单的string类,读书看报系列(一)

    对于这个类,写过程序的都知道应该含有的方法是 初始化.销毁.拼接.求长度.清除.判断是否为空等.还有一些操作符重载 一.先看初始化: 可以想到应该有默认构造的的.带有字符串的.带有默认字符的.还有一个 ...

  3. 【c++】简单的string类的几个基本函数

    // string的几个基本函数的实现 #include <iostream> #include <assert.h> #include <string.h> us ...

  4. 【Java】整理关于java的String类,equals函数和比较操作符的区别

    初学 Java 有段时间了,感觉似乎开始入了门,有了点儿感觉但是发现很多困惑和疑问而且均来自于最基础的知识折腾了一阵子又查了查书,终于对 String 这个特殊的对象有了点感悟大家先来看看一段奇怪的程 ...

  5. c++在string类源

    一:回想 (1)c++中的string类是在面试中和笔试中常常考的题目: project代码免费下载 string类的自行实现 (2)c++中的string类和fstream类合起来是处理外部数据的利 ...

  6. 全面深入介绍C++字符串:string类

    http://blog.csdn.net/liuliming3000/article/details/1809385 1 从C到C++ string类 2 string类的构造函数 3 string类 ...

  7. C++标准模板库Stand Template Library(STL)简介与STL string类

    参考<21天学通C++>第15和16章节,在对宏和模板学习之后,开启对C++实现的标准模板类STL进行简介,同时介绍简单的string类.虽然前面对于vector.deque.list等进 ...

  8. C++ char数组和string类简单使用总结

    使用char数组,进行字符串的操作,是c风格的操作方式. string是C++的风格,感觉string本质上就是一个vector<char> 以下代码详细展示了字符串的常见操作 #incl ...

  9. c++string类的简单介绍

    #include "iostream" #include "string" using namespace std; /*@author:浅滩 *family: ...

随机推荐

  1. CentOS 简单设置samba服务

    1.安装 yum -y install samba 2.设置配置文件 1) 备份Samba的配置文件:cp  /etc/samba/smb.conf  /etc/samba/smb.conf.bak ...

  2. 正则表达式preg_replace中危险的/e修饰符带来的安全漏洞问题

    mixed preg_replace ( mixed pattern, mixed replacement, mixed subject [, int limit]) /e 修饰符使 preg_rep ...

  3. Struts 2的拦截器(Interceptor)总结

     什么是Struts 2拦截器? 从软件构架上来说,拦截器是实现了面向方面编程的组件.它将影响了多个业务对象的公共行为封装到一个个可重用的模块,减少了系统的重复代码,实现功能的高度内聚,确保了业务对象 ...

  4. mysql添加一个用户

    对于添加mysql的远程访问用户,一定要记得刷新刷新系统权限表不然你怎么弄都是不成功的. insert into mysql.user(Host,User,Password) values(" ...

  5. 安卓刷机--fastboot线刷

    首先需要下载fastboot.exe,copy到system32文件夹下. 对于安卓系统的智能手机,同时按住开机键和音量减键,或手机连上电脑,输入adb reboot bootloader进入fast ...

  6. ENode框架Conference案例分析系列之 - 复杂情况的读库更新设计

    问题背景 Conference案例,是一个关于在线创建会议(类似QCon这种全球开发者大会).在线管理会议位置信息.在线预订某个会议的位置的,这样一个系统.具体可以看微软的这个项目的主页:http:/ ...

  7. Python黑帽编程1.3 Python运行时与包管理工具

    Python黑帽编程1.3  Python运行时与包管理工具 0.1  本系列教程说明 本系列教程,采用的大纲母本为<Understanding Network Hacks Attack and ...

  8. AutoMapper 最佳实践

    AutoMapper 是一个基于命名约定的对象->对象映射工具. 只要2个对象的属性具有相同名字(或者符合它规定的命名约定),AutoMapper就可以替我们自动在2个对象间进行属性值的映射.如 ...

  9. quick-cocos2d-x 2.2.3 rc版本中 crypto.md5file() 的C++实现在ANDROID上有BUG

    原来的版本是用fopen打开文件的,如果要从ANDROID的APK中取文件,直接就洗白了修改如下 void CCCrypto::MD5File(const char* path, unsigned c ...

  10. 你可能不知道的7个CSS单位

    如果你是一名前端开发工程师,一般px和em使用频率比较高.但是今天本文的重点是介绍一些我们使用很少.甚至么有听说的单位. 一.重温em <style type="text/css&qu ...