C++ - string 基本版
2015-10-03 21:43
681 查看
真正去了解如何写一个string类的时候,发现有好多知识点。
复制控制(复制构造函数、赋值操作符、析构函数)
运算符重载(+, ==, !=, <, <=, >, >=, +=, []等等)
深拷贝(对于字符串拷贝的处理)
友元(cin, cout)
内联函数(为了提高效率,这些函数都是内联函数)
const的用法(返回值为常量、常量函数、输入为常量)
引用(输入为引用、返回值为引用(如+, []))
异常安全(operator=)
这些也还只是基本版的内容,还有
隐式共享写时拷贝(智能指针)
C++11的右值引用、Move语义
iterator
gcc中string(basic_string)的写法又是另外一种层面的东西了……
本文给出基本版的代码
最后附上一些参考资料。
STL 的string类怎么啦?
意图(Intention)、规格(Specification)、实现(Implementation)
标准C++类string的Copy-On-Write技术(一)
引用计数器(智能指针)
C++面试中string类的一种正确写法
C++ string实现原理
C++ string类的隐式共享写时拷贝的实现及设计要点
C++中String类的实现
复制控制(复制构造函数、赋值操作符、析构函数)
运算符重载(+, ==, !=, <, <=, >, >=, +=, []等等)
深拷贝(对于字符串拷贝的处理)
友元(cin, cout)
内联函数(为了提高效率,这些函数都是内联函数)
const的用法(返回值为常量、常量函数、输入为常量)
引用(输入为引用、返回值为引用(如+, []))
异常安全(operator=)
这些也还只是基本版的内容,还有
隐式共享写时拷贝(智能指针)
C++11的右值引用、Move语义
iterator
gcc中string(basic_string)的写法又是另外一种层面的东西了……
本文给出基本版的代码
#include <iostream> #include <vector> #include <string> #include <iomanip> // setw #include <cstdio> using namespace std; class MyString { // inline public: // constructor MyString(const char* str = NULL); MyString(const MyString&); MyString(size_t, char); // ? memset? // destructor ~MyString(); bool empty(); size_t size() const; // string::size_type? const char* c_str() const; void swap(MyString&); // operator +, ==, !=, <, <=, >, >=, += char& operator[](size_t); // unsigned int?? MyString& operator=(const MyString&); MyString operator+(const MyString&) const; bool operator==(const MyString&); // friend istream, ostream friend istream& operator>>(istream&, MyString&); friend ostream& operator<<(ostream&, MyString&); private: char *m_data; }; int main() { MyString mstr, s1, s2; cin >> mstr; cout << mstr << endl; mstr[0] = 'k'; cout << mstr << endl; s1 = s2 = mstr; s2[2] = '3'; cout << s1 << " " << (s1 == s2) << " " << s2 << endl; MyString s3(10, 'm'); cout << s3 << endl; return 0; } inline MyString::MyString(const char* str) { // error C2572: “MyString::MyString”: 重定义默认参数 : 参数 1 // 去掉 = NULL if (!str) { m_data = new char[1]; m_data[0] = '\0'; } else { m_data = new char[strlen(str) + 1]; strcpy(m_data, str); } } inline MyString::MyString(const MyString &object) { m_data = new char[object.size() + 1]; strcpy(m_data, object.c_str()); } inline MyString::MyString(size_t n, char ch) { m_data = new char[n + 1]; memset(m_data, ch, n); m_data = '\0'; } inline MyString::~MyString() { delete []m_data; } size_t MyString::size() const { return strlen(m_data); } const char* MyString::c_str() const { return m_data; } void MyString::swap(MyString &rhs) { std::swap(m_data, rhs.m_data); } char& MyString::operator[](size_t i) { // 考虑错误处理 return m_data[i]; } MyString& MyString::operator=(const MyString& rhs) { if (this != &rhs) { MyString temp(rhs); swap(temp); } return *this; } bool MyString::operator==(const MyString& rhs) { return strcmp(m_data, rhs.c_str()) ? false : true; } MyString MyString::operator+(const MyString& rhs) const { MyString newS; //if (!rhs.m_data) { // 不可能为NULL // newS = *this; //} //else if (!this->m_data) { // newS = rhs.m_data; //} //else { newS.m_data = new char[size() + rhs.size() + 1]; strcpy(newS.m_data, m_data); strcat(newS.m_data, rhs.m_data); //} return newS; } istream& operator>>(istream& in, MyString& rhs) { // 第一种方法:字符串长度受限 //char temp[255]; //in >> setw(255) >> temp; ////rhs = MyString(temp); // ok //rhs = temp; ////strcpy(rhs.m_data, temp); // ??有问题,确实有问题,m_data并没有分配空间,因此也可以先分配空间再拷贝 //return in; // 第二种方法:字符串长度不受限,但在个别情况下有bug,详见注释 //const int BUFFER_SIZE = 255; // 可以以5来做测试 //char buffer[BUFFER_SIZE]; //char *end = buffer + BUFFER_SIZE - 1; //rhs = ""; // clear //do { // *end = '#'; // //in >> setw(BUFFER_SIZE) >> buffer; // 如果输入恰好是BUFFER_SIZE - 1,则会出问题 // //in.get(buffer, BUFFER_SIZE); // 并不能以空格分隔,直接输入换行也会出问题,暂时还不清楚为什么?难道是因为get了两次? // in.get(buffer, BUFFER_SIZE, ' '); // 如果以空格分隔,又不能识别换行 // rhs += buffer; //} while (*end == '\0'); //in.get(); //// http://www.cplusplus.com/reference/istream/istream/get/ //// The delimiting character is not extracted from the input sequence if found, //// and remains there as the next character to be extracted from the stream (see //// getline for an alternative that does discard the delimiting character). //return in; // 第三种方法:单字符处理,尝试get(char &c) const int BUFFER_SIZE = 255; // 可以以5来做测试 char buffer[BUFFER_SIZE]; int i = 0; char ch; rhs = ""; // 标准输入流忽略空格和\n // http://www.cplusplus.com/reference/istream/istream/operator%3E%3E/ do { in.get(ch); } while (ch == ' ' || ch == '\n'); while (true) { if (ch == ' ' || ch == '\n') { buffer[i] = '\0'; rhs += buffer; break; } else { buffer[i++] = ch; if (i == BUFFER_SIZE - 1) { buffer[i] = '\0'; rhs += buffer; i = 0; } } in.get(ch); } return in; } ostream& operator<<(ostream& out, MyString& rhs) { out << rhs.m_data; return out; }
最后附上一些参考资料。
STL 的string类怎么啦?
意图(Intention)、规格(Specification)、实现(Implementation)
标准C++类string的Copy-On-Write技术(一)
引用计数器(智能指针)
C++面试中string类的一种正确写法
C++ string实现原理
C++ string类的隐式共享写时拷贝的实现及设计要点
C++中String类的实现
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android之获取手机上的图片和视频缩略图thumbnails
- android string.xml文件中的整型和string型代替
- Android java 与 javascript互访(相互调用)的方法例子
- 关于指针的一些事情
- android上改变listView的选中颜色
- String.intern
- c++ primer 第五版 笔记前言
- share_ptr的几个注意点
- 用PS实现纹理浮雕效果代码
- 用vbs实现cmd功能的代码
- Prototype源码浅析 String部分(二)
- 用双网卡实现三机互联
- Ruby中的String对象学习笔记
- Lua中调用C++函数示例
- Lua教程(一):在C++中嵌入Lua脚本
- Lua教程(二):C++和Lua相互传递数据示例
- PostgreSQL ERROR: invalid escape string 解决办法
- C#中实现判断某个类是否实现了某个接口
- DL.DT.DD实现左右的布局简单例子第1/2页