6.string的模拟实现(三)
一.流提取实现补充
原来的实现:
istream& operator>> (istream& is, string& str){str.clear();char ch = is.get();while (ch != ' ' && ch != '\n'){str += ch;ch = is.get();}return is;}
我们不难发现,我们一直慢慢的get(),但是,进行插入的时候,大多数时候会进行扩容(有资源的消耗)
istream& operator>> (istream& is, string& str){str.clear();char buff[128];int i = 0;char ch = is.get();while (ch != ' ' && ch != '\n'){buff[i++] = ch;if(i == 127){buff[i] = '\0';str += buff;i = 0;}ch = is.get();}if(i != 0){buff[i] = '\0';str += buff;}return is;}
我们这里开128个字节的buff数组,等到了128个字节的时候,我们才进行一次性加到str上面,
这样就减少了扩容的消耗
二.拷贝的写法补充
// s2(s1)// 传统写法// string::string(const string& s)// {// _str = new char[s._capacity + 1];// strcpy(_str, s._str);// _size = s._size;// _capacity = s._capacity;// }// 现代写法string::string(const string& s){string tmp(s._str);std::swap(tmp._str,_str);std::swap(tmp._size,_size);std::swap(tmp._capacity,_capacity);}
// s2(s1)// 传统写法// string::string(const string& s)// {// _str = new char[s._capacity + 1];// strcpy(_str, s._str);// _size = s._size;// _capacity = s._capacity;// }// 现代写法string::string(const string& s){string tmp(s._str);// std::swap(tmp._str,_str);// std::swap(tmp._size,_size);// std::swap(tmp._capacity,_capacity);swap(tmp);}
又因为我们重新进行写了swap,所以我们可以进行直接调用
三.赋值的写法补充
// s1 = s3// s1 = s1// string& string::operator=(const string& s)// {// if (this != &s)// {// char* tmp = new char[s._capacity + 1];// strcpy(tmp, s._str);// delete[] _str;// _str = tmp;// _size = s._size;// _capacity = s._capacity;// }// return *this;// }string& string::operator=(const string& s){if (this != &s){string tmp(s);swap(tmp);}return *this;}
还有一个更简单的写法:
string& string::operator=(string tmp){swap(tmp);return *this;}
效率上面没有提升,只是没有自己干这个事情
四.写时拷贝
https://coolshell.cn/articles/12199.html (写时拷贝)
https://coolshell.cn/articles/10478.html (面试时怎么写string类)
这个引用计数的写时拷贝,有什么用呢?
Linux下的string的设计方案就是这样的
C++中(在流运算符下 c_str() 是打不出地址的,只能用(void*)s1.c_str());
C++后续增加了右值引用和移动语义就没什么意义了