簡體   English   中英

C++ 字符串 class 實現

[英]C++ String class implementation

我的項目要求在 C++ 中實現字符串 class,但是,我對公共 function 之一感到困惑

class String
{
private:
    char* buffer;
    int size;
    
public:
    // Initializes a string to be empty (i.e., its length will
    // be zero and toChars() will return "").
    String();

    // Initializes a string to contain the characters in the
    // given C-style string, which is assumed to be null-terminated.
    String(const char* chars);

    // Initializes a string to be a copy of an existing string,
    // meaning that it contains the same characters and has the
    // same length.
    String(const String& s);

    // Destroys a string, releasing any memory that is being
    // managed by this object.
    ~String() noexcept;
};

除了String(const char* chars); function,我都正確實現了它們,但我對如何實現這一點沒有任何線索。

編輯:由於不能使用 c++ 標准庫,我必須不使用strlen()來計算chars的大小

String::String(){
    size = 0;
    buffer = nullptr;
}

String::String(const char* chars){
    int i = 0;
    for (char* p = chars;*p != '\0'; p++){
        ++i;
    }
    size = i;

    buffer = new char[size+1];
    i = 0;
    for(;i<size;i++){
        buffer[i] = chars[i];
    }

    buffer[i] = '\0';
}

String::String(const String& s){
    size = s.size;
    buffer = new char[size];
    for int(i=0;i<size;i++){
        buffer[i] = s.buffer[i];
    }
}

String::~String() noexcept{
    delete[] buffer;
}

您應該使用std::vector<char>作為緩沖區,這樣您就不會顯式調用new[]delete[] std::vector是 C++ 的一部分(並且已經存在了很長時間),所以這肯定是“在 C++ 中實現 [ing] 字符串 class ......”(並且不使用std::string

class String final
{
    std::vector<char> buffer;

public:
    String() = default;
    String(const char* chars){
       auto begin = chars;
       auto end = begin + strlen(chars);
       buffer.insert(buffer.begin(), begin, end);
   }
   String(const String& s){
      buffer = s.buffer;
   }
   ~String() = default;
};

注意現在各種構造函數有多簡單。 這具有避免內存泄漏和異常安全的額外優勢; 並且您甚至不必(幾乎)考慮這些問題。

如果你真的想避免使用std::vector (為什么?它非常適合這種情況),那么至少你應該使用std::unique_ptr<char[]> (或者可能是std::shared_ptr<char[]> ) 添加到 C++11。

class String final
{
    std::unique_ptr<char[]> buffer;
public:
    String() = default;
    ~String() = default;
    String(const String&) = delete;
    String& operator=(const String&) = delete;
    String(const char* chars) {
       const auto len = strlen(chars);
       buffer = std::make_unique<char[]>(len + 1);
       strcpy(buffer.get(), chars);
    }
};

您最近的編輯沒有多大意義。 strlen()可以看出,即使是看似“簡單”的 function 也很難做到正確; 這就是我們有標准庫的原因。 如果您不能使用任何標准庫,那么甚至沒有任何方法可以動態分配 memory ,就像使用malloc()完成的那樣。

您分配的 memory 數量存在一些差異,它們會回來咬你。

  • 您的默認構造函數不分配任何東西。
  • 您的轉換構造函數分配size + 1 char s。
  • 您的復制構造函數分配size char s。
  • 您還需要添加移動構造函數和復制+移動賦值運算符。

我建議您在各處分配size + 1為 null 終結器留出空間。 這也將使實現評論示例中提到的toChars() function 變得非常容易:

char* String::toChars() { return buffer; }

由於您不允許使用任何標准庫函數,例如std::strlen()std::memcpy() ,並且由於您可能不止一次需要這樣的函數,您可以編寫類似的函數自己而不是將該代碼放在 class 的多個地方的函數中。 定義一次,多次使用。

// a function to get the length of a null terminated C string
unsigned len(const char* chars) {
    unsigned result = 0;
    for(;*chars != '\0'; ++chars, ++result) {}
    return result;
}

// A function to copy a certain amount of chars
void cpy(const char* from, char* to, unsigned len) {
    for(; len; --len, ++from, ++to) {
        *to = *from;
    }
}

有了這些,您的構造函數將非常簡單。 我故意不在這里使用成員初始化器列表- 但請檢查它們。

String::String() {                   // default ctor
    size = 0;
    buffer = new char[size + 1]{};   // {} makes it zero initialized
    // buffer[0] = '\0';             // or you could do this instead
}

String::String(const char* chars) {  // converting ctor
    size = len(chars);               // use the len() function
    buffer = new char[size + 1];
    cpy(chars, buffer, size + 1);    // and use the cpy() function
}

String::String(const String& s) {    // copy ctor
    size = s.size;
    buffer = new char[size + 1];
    cpy(s.buffer, buffer, size + 1); // use the cpy() function again
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM