文章标题 原创 翻译 转载 文章内容 正确实现String可以考察C++的一些基本功,稍不注意就会出错,下面来列举一下关键点: 1. 构造函数,拷贝构造,赋值操作符是必须的; 2. 成员初始化列表执行顺序; 3. c_str()不要返回空指针; 4. 实现swap函数; 5. 分配内存的时候要用外面传进来的size; 6. 赋值操作符的实现方法:参数以传值的形式; 7. 析构函数delete []; 先看下代码: ``` class String { public: String() : len_(0) , buffer_(nullptr) { } String(const char *str, size_t size) : len_(size) , buffer_(size ? new char[size + 1] : nullptr) { if (buffer_) { std::copy(str, str + len_, buffer_); buffer_[size] = '\0'; } } String(const char *str) : String(str, strlen(str)) { } String(const String &str) : String(str.buffer_, str.len_) { } ~String() { delete[] buffer_; } void swap(String& right) { std::swap(len_, right.len_); std::swap(buffer_, right.buffer_); } // 传统写法 //String& operator= (const String &str) //{ // String tmp(str); // this->swap(tmp); // return *this; //} String& operator=(String str) { this->swap(str); return *this; } size_t size() { return len_; } const char* c_str() { return buffer_ ? buffer_ : ""; } private: size_t len_; char *buffer_; }; ``` # 简化代码 第二个构造函数很重要,有了它后面的构造函数写起来就方便多了。否则你要写多个类似下面的代码: ``` String(const char *str, size_t size) : len_(size) , buffer_(size ? new char[size + 1] : nullptr) { if (buffer_) { std::copy(str, str + len_, buffer_); buffer_[size] = '\0'; } } ``` # 成员初始化列表 注意:成员初始化列表是以成员定义的顺序来进行初始化的。 如果成员变量定义的是如下顺序: ``` private: char *buffer_; size_t len_; ``` 而构造函数是下面写法是会出错的: ``` // 错误的写法 String(const char *str, size_t size) : len_(size) , buffer_(len_ ? new char[len_ + 1] : nullptr) { if (buffer_) { std::copy(str, str + len_, buffer_); buffer_[size] = '\0'; } } ``` 根据len_的长度来创建buffer_,看起来先将size赋值给了len_然后再使用len_,但其实在初始化buffer_的时候len_还没有被初始化,所以导致buffer_一直为nullptr。为了避免这个错误你需要注意成员变量的初始化顺序,但是这样做并不好,当成员变量多了的时候很难注意到这个问题。所以最好的做法就是:在成员初始化列表中使用传进来的参数,不要使用赋值后的参数。 # 字符串以'\0'结尾 由于实现的是字符串所以要多分配一个字符已'\0'结尾,如果是其他buffer,如:int[]就不需要了。 # 参数通过传值的方式实现赋值操作符 ``` String& operator=(String str) { this->swap(str); return *this; } ``` 原理是:str传进来的是一个临时拷贝,当swap之后,把当前this的buffer_交换给了临时str,临时str的buffer_赋值给了this,当临时str析构的时候它帮我们把this先前的buffer_给释放了,而它的buffer_给了this。 文章类别 Python Mobile Android Java Shell Life Database Bug Windows IOS Tools Boost Node.js Mac Product Tips C/C++ Golang Javascript React Qt MQ MongoDB Design Web Linux LLM ChatGPT RAG AI 提交