cpp笔记与思考-string与实现

C/C++笔记
深入理解并部分实现一个cpp的string类

追根溯源,剖析STL是个享受的过程。

类构造

// 类构造
class String
{
public:
    String(const char *str = NULL);	// 构造函数
    String(const String &str);		// 拷贝构造函数
    ~String();						// 析构函数

    String operator+(const String &str) const;	// 重载+
    String& operator=(const String &str);		// 重载=
    String& operator+=(const String &str);		// 重载+=
    bool operator==(const String &str) const;	// 重载==
    char& operator[](int n) const;				// 重载[]

    int getLength() const;		//获取长度

    friend istream& operator>>(istream &is, String &str); // 输入
    friend ostream& operator<<(ostream &os, String &str); // 输出

private:
    char *data;		//字符串
};

部分实现

string类实际上还拥有vector类的大部分方法(好像是全部?),在表现上

理解string类为vector<char>也可以,但是string有对+等运算符的重载,同时内寸管理方式也不同。

#include <iostream>
#include <cstring>

using namespace std;

// 实现 String 类
class String
{
public:
    // 普通构造函数
    String(const char *str = NULL) {
    if (str == NULL) {
        m_data = new char[1];
        m_data = '\0';
    } else {
        int length = strlen(str);

        m_data = new char[length + 1];

        strcpy(m_data, str);
    }			
    }

    // 拷贝构造函数,深复制
    String(const String &other) {
    if (!other.m_data) {
        m_data = NULL;
    }

    m_data = new char[strlen(other.m_data) + 1];

    strcpy(m_data, other.m_data);
    }

    // 析构函数
    ~String() {
    if (m_data) {
        delete[] m_data;
        m_data = NULL;
    }
    }

    // 重载 + 字符串连接, 不能返回引用
    String operator+(const String &other) const {
    String newString;

    delete[] newString.m_data;

    if (!other.m_data) {
        newString = *this;	
    } else if (!m_data) {
        newString = other;
    } else {
        newString.m_data = new char[strlen(m_data) + strlen(other.m_data) + 1];
        strcpy(newString.m_data, m_data);
        strcat(newString.m_data, other.m_data);
    }

    return newString;
    }

    // 重载 = 赋值
    String& operator=(const String &other) {
    if (this != &other) {
        delete[] m_data;

        if (!other.m_data) {
        m_data = NULL;
        } else {
        m_data = new char[strlen(other.m_data) + 1];
        strcpy(m_data, other.m_data);
        }
    }

    return *this;
    }

    // 重载 ==
    bool operator==(const String &other) const {
    if (strlen(m_data) != strlen(other.m_data)) {
        return false;
    } else {
            return strcmp(m_data, other.m_data) ? false : true;
    }
    }

    // 重载 +=
    String& operator+=(const String &other) {
        char *newData = new char[strlen(m_data) + strlen(other.m_data) + 1];

    strcpy(newData, m_data);
    strcat(newData, other.m_data);

    delete[] m_data;

    m_data = newData;

    return *this;
    }

    // 重载 []
    char& operator[](int n) const {
    if (n >= strlen(m_data)) {
        return m_data[strlen(m_data) - 1];
    }

    return m_data[n];
    }

    // 获取长度
    int getLength() const {
    return strlen(m_data);
    }

    // 输入, 重载输入操作,需要先申请一块内存,用于存放输入字符串
    friend istream& operator>>(istream &is, String &str) {
    char strTemp[100];

    memset(strTemp, 0, sizeof(strTemp));

    is >> strTemp;

    str.m_data = new char[strlen(strTemp) + 1];

    strcpy(str.m_data, strTemp);

    return is;
    }

    // 输出
    friend ostream& operator<<(ostream &os, String &str) {
    os << str.m_data;

    return os;
    }

private:
    char *m_data;
};

// 测试
void test(){
    String s;

    cin >> s;

    cout << s << " : " << s.getLength() << endl;

    
    String s1(s);
    
    cout << s1 << " : " << s1.getLength() << endl;

    const char *str = "Hello";

    String s2(str);

    cout << s2 << " : " << s2.getLength() << endl;


    char str1[] = "world!";

    String s3(str1);

    cout << s3 << " : " << s3.getLength() << endl;

    String s4 = s3;

    if (s4 == s3) {
    cout << "s3 == s4" << endl;
    } else {
    cout << "s3 != s4" << endl;
    }

    String s5 = s3 + s4;

    cout << s5 << " : " << s5.getLength() << endl;
    
    s3 += s4;

    if (s5 == s3) {
    cout << "s5 == s3" << endl;
    } else {
    cout << "s5 != s3" << endl;
    }

    cout << s5[5] << endl;
}

int main()
{
    test();
    return 0;
}

Reference