C++ - string 基本版

来源:互联网 发布:mssql数据库管理工具 编辑:程序博客网 时间:2024/06/08 04:20

真正去了解如何写一个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 { // inlinepublic:    // 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[n] = '\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类的实现

0 0