MST

星途 面试题库

面试题:自定义实现类似C++ string类的功能

假设C++标准库中没有string类,请你自定义一个MyString类,实现其基本功能,包括构造函数、析构函数、拷贝构造函数、赋值运算符重载,以及常用的字符串操作函数如拼接、比较等,并说明在实现过程中如何处理内存管理和异常安全问题。
23.6万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试
#include <iostream>
#include <cstring>

class MyString {
private:
    char* data;
    size_t length;

public:
    // 构造函数
    MyString(const char* str = nullptr) {
        if (str == nullptr) {
            length = 0;
            data = new char[1];
            data[0] = '\0';
        } else {
            length = std::strlen(str);
            data = new char[length + 1];
            std::strcpy(data, str);
        }
    }

    // 析构函数
    ~MyString() {
        delete[] data;
    }

    // 拷贝构造函数
    MyString(const MyString& other) {
        length = other.length;
        data = new char[length + 1];
        std::strcpy(data, other.data);
    }

    // 赋值运算符重载
    MyString& operator=(const MyString& other) {
        if (this != &other) {
            delete[] data;
            length = other.length;
            data = new char[length + 1];
            std::strcpy(data, other.data);
        }
        return *this;
    }

    // 拼接函数
    MyString& append(const MyString& other) {
        size_t newLength = length + other.length;
        char* newData = new char[newLength + 1];
        std::strcpy(newData, data);
        std::strcat(newData, other.data);
        delete[] data;
        data = newData;
        length = newLength;
        return *this;
    }

    // 比较函数
    int compare(const MyString& other) const {
        return std::strcmp(data, other.data);
    }

    // 获取字符串长度
    size_t size() const {
        return length;
    }

    // 获取C风格字符串
    const char* c_str() const {
        return data;
    }
};

内存管理

  1. 构造函数:根据传入的字符串分配足够的内存空间,并复制字符串内容。如果传入 nullptr,分配一个长度为1的空间存储空字符。
  2. 析构函数:释放构造函数中分配的内存,避免内存泄漏。
  3. 拷贝构造函数和赋值运算符重载:先释放自身已有的内存,再根据传入对象的内容分配新的内存并复制。

异常安全问题

  1. 资源分配即初始化(RAII):使用 new 分配内存时,如果内存分配失败会抛出 std::bad_alloc 异常。由于对象在构造函数中分配内存后立即初始化成员变量,在析构函数中释放内存,所以即使在构造函数或其他成员函数中抛出异常,也能保证已分配的内存被正确释放,避免内存泄漏。
  2. 异常安全的赋值运算符重载:在赋值运算符重载中,先检查是否是自赋值(this != &other),然后释放旧的内存,再分配新的内存并复制数据。如果在分配新内存时抛出异常,原对象的状态不会改变,仍然保持有效,符合异常安全的基本保证。如果需要提供强异常安全保证,可以先创建一个临时对象,进行所有可能抛出异常的操作,然后再交换临时对象和当前对象的内容。