简体   繁体   English

C++ 字符串 class 实现

[英]C++ String class implementation

My project asks to implement a string class in C++, however, I'm confused about one of the public function我的项目要求在 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;
};

Besides String(const char* chars);除了String(const char* chars); function, I implemented all of them correctly, but I don't have any clues about how to implement this one. function,我都正确实现了它们,但我对如何实现这一点没有任何线索。

Edited: Since c++ standard library cannot be used, I have to compute the size of chars by not using strlen()编辑:由于不能使用 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;
}

You should be using std::vector<char> for your buffer so that you don't explicitly call new[] and delete[] .您应该使用std::vector<char>作为缓冲区,这样您就不会显式调用new[]delete[] std::vector is part of C++ (and has been for a long time), so this certainly is "implement[ing] a string class in C++..." (and does not use std::string ). 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;
};

Notice how much simpler the various constructors are now.注意现在各种构造函数有多简单。 This has the added advantage of avoiding memory-leaks and being exception safe;这具有避免内存泄漏和异常安全的额外优势; and without you having to even (hardly) think about those concerns.并且您甚至不必(几乎)考虑这些问题。

If you really want to avoid using std::vector (why? it's perfect for this case), then at the very least you should use std::unique_ptr<char[]> (or maybe std::shared_ptr<char[]> ) which were added to C++11.如果你真的想避免使用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);
    }
};

Your most recent edit doesn't make much sense.您最近的编辑没有多大意义。 As can be seen from strlen() even an seemingly "easy" function can be hard to get right;strlen()可以看出,即使是看似“简单”的 function 也很难做到正确; that's why we have standard libraries.这就是我们有标准库的原因。 And if you can't use any standard library, then there's not even any way to dynamically allocate memory as that's done with malloc() .如果您不能使用任何标准库,那么甚至没有任何方法可以动态分配 memory ,就像使用malloc()完成的那样。

There are some differences in how much memory you allocate which will come back and bite you.您分配的 memory 数量存在一些差异,它们会回来咬你。

  • Your default constructor doesn't allocate anything.您的默认构造函数不分配任何东西。
  • Your converting constructor allocates size + 1 char s.您的转换构造函数分配size + 1 char s。
  • Your copy constructor allocates size char s.您的复制构造函数分配size char s。
  • You also need to add a move constructor and copy+move assignment operators.您还需要添加移动构造函数和复制+移动赋值运算符。

I suggest that you allocate size + 1 everywhere to leave room for the null terminator.我建议您在各处分配size + 1为 null 终结器留出空间。 This will also make it really easy to implement the toChars() function mentioned in the comments Example:这也将使实现评论示例中提到的toChars() function 变得非常容易:

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

Since you're not allowed to use any of the standard library functions, like std::strlen() or std::memcpy() , and since you are likely going to need functions like that more than once, you could write similar functions yourself instead of putting that code inside the functions of your class in multiple places.由于您不允许使用任何标准库函数,例如std::strlen()std::memcpy() ,并且由于您可能不止一次需要这样的函数,您可以编写类似的函数自己而不是将该代码放在 class 的多个地方的函数中。 Define them once and use them many times.定义一次,多次使用。

// 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;
    }
}

With those, your constructors would be pretty simple.有了这些,您的构造函数将非常简单。 I've deliberately not used the member initializer-lists here - but please do check them out.我故意不在这里使用成员初始化器列表- 但请检查它们。

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