1. MyString构造函数要区分输入参数是否为空;
strlen在参数为NULL(等价于0,’\0’)时会抛异常,所以MyString的构造函数需要判断是否为空指针;
2. 构造函数生成的对象原来并不存在,所以不需要delete[] m_data;
3. 对于拷贝赋值函数,操作步骤分为三步:
- 防止自赋值;
- delete 当前内存,然后向当前对象赋值;
- 返回当前对象引用;(目的是为了方便链式调用,如a = b = c ;)
#include <iostream>
#include <cstring>
class MyString {
public:
MyString(const char* cstr=0){
if(cstr) { //strlen在参数为NULL(等价于0,'\0')时会抛异常才会有这步判断
m_data = new char[strlen(cstr)+1];
strcpy(m_data, cstr);
} else {
m_data = new char[1];
m_data = '\0';
}
}
~MyString() {
delete[] m_data;
}
MyString(const MyString& str) {
m_data = new char[strlen(str.m_data)+1];
strcpy(m_data, str.m_data);
}
MyString(MyString&& str) noexcept : m_data(str.m_data) {
str.m_data = nullptr;
}
MyString& operator=(const MyString& str) {
if(this == &str)
return *this;
delete[] m_data;
m_data = new char[strlen(str.m_data)+1];
strcpy(m_data, str.m_data);
return *this;
}
MyString& operator=(MyString&& str) noexcept{
if(this == &str)
return *this;
delete m_data;
m_data = str.m_data;
str.m_data = nullptr;
return *this;
}
char* get_c_str() const {return m_data;}
private:
char* m_data;
};
void print(const MyString& str) {
std::cout << str.get_c_str() << std::endl;
}
int main(int argc, char** argv) {
MyString str1("str1");
print(str1);
MyString str2(str1);
print(str2);
MyString str3;
str3 = str2;
print(str3);
MyString str4 = std::move(str2);
print(str4);
MyString str5;
str5 = std::move(str3);
print(str5);
}