当前位置: 首页 > news >正文

js特效演示网站网站策划书优势怎么分析

js特效演示网站,网站策划书优势怎么分析,一个网站两个域名吗,重庆大渝网官网目录 1.构造函数 模拟实现 2.析构函数 模拟实现 3.string遍历 3.1 c_str、size、lenth、capacity等 模拟实现 3.2 字符串元素访问 3.2.1 []操作符重载、at 模拟实现 3.2.2 front、back等 3.3 迭代器 模拟实现 4.赋值操作 4.1 赋值重载函数 模拟实现 4.2 assig…目录 1.构造函数 模拟实现 2.析构函数 模拟实现 3.string遍历 3.1 c_str、size、lenth、capacity等 模拟实现 3.2 字符串元素访问 3.2.1 []操作符重载、at 模拟实现 3.2.2 front、back等 3.3 迭代器 模拟实现 4.赋值操作 4.1 赋值重载函数 模拟实现 4.2 assign函数 ​编辑 5.size与capacity修改 5.1 shrink_to_fit缩容、reserve扩容 模拟实现 5.2 resize函数 模拟实现 5.3 clear函数 模拟实现 6.增删查改 6.1 string插入 6.1.1 push_back尾插字符 模拟实现 6.1.2 append尾插字符串 模拟实现 6.1.3 操作符重载 模拟实现 6.1.4 insert随机插入 模拟实现 6.2 string删除 模拟实现 6.3 string替换 6.4 string查找 模拟实现 6.5 字符串截取 模拟实现 7.交换string对象的值 模拟实现 8.比较操作符重载 模拟实现 9.输入和输出 9.1 流插入 9.1.1  流插入运算符重载 模拟实现 9.2 流提取 9.2.1 流提取操作符重载 模拟实现 9.2.2 getline函数 模拟实现 10.拷贝构造函数、赋值重载运算符的改进 在C语言中我们在处理字符串时采取的方案是使用一个字符数组这样的方式对于我们管理和使用字符串会有一些麻烦。所以在C中一方面兼容了C语言中的字符串形式另一方面则是通过内置的string类来进行管理。C内置的string类配备了许多方便的成员函数这对我们使用C处理字符串提供了极大的便利这篇文章主要是总结string类的使用方法以及一些特点同时对于一些常用的函数我们会自主模拟一份以帮助我们更细致地掌握细节。 1.构造函数 对于一个类而言首要考虑的就是构造函数。C为string的构造重载了许多函数在使用string类的时候需要注意包含头文件 #includestring 。 void Test1() { //default (1): string(); //copy(2): string(const string str); //substring(3): string(const string str, size_t pos, size_t len npos); //from c - string(4): string(const char* s); //from sequence(5): string(const char* s, size_t n); //fill(6): string(size_t n, char c);string s1;string s2(hello world!);string s3(s2);string s4(s2,3,5);string s5(s2,3,10);string s6(s2,3);string s7(good luck, 3);string s8(7,#);cout s1 endl;cout s2 endl;cout s3 endl;cout s4 endl;cout s5 endl;cout s6 endl;cout s7 endl;cout s8 endl; } 对于以上的构造函数进行解释 (1)默认构造 (2)拷贝构造 (3)部分拷贝str字符串的pos下标开始len个长度。如果超出str范围或未传参则会一直拷贝到结尾。npos值为-1对于size_t则是最大值 (4)使用C-string构造 (5)拷贝s字符串的前n个字符 (6)n个c字符构造 模拟实现 在我们模拟实现一个string类的时候首先需要注意命名空间的问题。标准库中的标识符存在std中所以我们需要重新定义一个命名空间并在该命名空间中完成和string类有关的函数的实现这样因为命名空间隔绝所以可以放心使用函数名。在类外使用自主实现的string时需要记得指定命名空间域。 string类中有三个成员变量存储字符串的指针char*记录字符串长度的整型和记录存储长度上限的整型。 构造函数初始化使用初始化列表要注意成员变量的初始化。需要注意的是实际开辟的空间大小需要比capacity大一个因为需要存储一个\0。 using namespace std; //展开std命名空间对标识符的搜索先局部在全局所以在以下m_string的命名空间中所有标识符会优先搜索局部即m_string中的标识符namespace m_string //定义一个新的命名空间将我们实现的string放在其中防止和std中的string产生冲突 {class string{public://构造函数string(const char* str ) //构造函数全缺省输入c字符串当无输入的时候也有一个\0不会产生错误:_size(strlen(str)),_capacity(_size),_str(new char[_capacity 1]) //初始化列表初始化顺序按照成员变量声明顺序_str需要多开一个空间存储\0{strcpy(_str, str); //使用strcpy进行赋值操作}//拷贝构造函数string(const string s) //string对象中有_str需要深拷贝{_str new char[s._capacity 1];strcpy(_str, s._str);_capacity s._capacity;_size s._size;}private:size_t _size;size_t _capacity;char* _str;} } 2.析构函数 析构函数的用法没什么特殊的销毁对象的时候自动调用。 模拟实现 因为是释放char*的空间析构函数需要自己写一份。 //析构函数~string() //由于_str所以需要主动实现析构函数{delete[] _str;_str NULL;_capacity _size 0;} 3.string遍历 3.1 c_str、size、lenth、capacity等 完成string遍历的操作首先需要有手段获取string对象的信息string类中有许多函数来提供访问对象的基本信息的渠道。 void Test1() {//length和size没有区别都是返回字符串长度string s1(Say hello to the world!);cout s1.size() endl;cout s1.length() endl;//最大字符串长度很少使用cout s1.max_size() endl;//返回容量cout s1.capacity() endl; } 模拟实现 //c_str作用是返回一个C字符串const char* c_str() const //函数内和返回值都不会修改所以const修饰this指针const修饰返回值{return _str;}//size返回string的长度size_t size() const{return _size;}//capacity返回string容量size_t capacity() const{return _capacity;} 3.2 字符串元素访问 除此之外我们还需要能够像C语言一样通过下标等方式访问字符串的元素。因此C中也有不同的成员函数来提供诸多访问方式。 3.2.1 []操作符重载、at 在C中我们可以看到[]操作符被重载了两份分别对应const和非const对象。可以通过下标访问对应位置的字符at和[]的功能一致。 string s1(hello world);for (int i 0; i s1.size(); i)//size()函数返回字符串长度不包含\0{cout s1[i] ;s1[i];cout s1[i] ;//[]重载可读可写//char operator[] (size_t pos); //const字符串使用const修饰的[]重载返回const char不可以写操作//const char operator[] (size_t pos) const;}cout endl;//[]、at()功能一样返回对应位置字符string s1(hello world);cout s1[3] endl;cout s1.at(3) endl; 模拟实现 //[]重载需要重载const和非const版本保证非const对象可以被修改而const对象不可修改char operator[](size_t pos) //针对非const对象返回对应下标字符的引用{return _str[pos];}const char operator[](size_t pos) const //针对const对象返回对应下标字符的const引用{return _str[pos];} 3.2.2 front、back等 front和back函数用于返回头元素和尾元素使用场景很少其实现更多的是为了和其他STL容器保持一致。 //front()、back()分别返回头尾字符cout s1.front() endl;cout s1.back() endl; 3.3 迭代器 迭代器的主要作用就是遍历容器内的元素使用迭代器有利于面向对象的封装特性迭代器在提供遍历方案的同时隐藏了容器的具体实现方法更加安全。除此之外使用迭代器可以让我们不用在乎容器中的数据类型迭代器会自动帮我们处理这就让其使用起来更加方便。 迭代器在使用时需要定义一个iterator类型的变量使用string类中的begin函数与end函数获得容器中第一个元素和最后一个元素的标识然后进行遍历访问即可。 //迭代器it类似于一个指针通过it访问元素时需要解引用begin和end分别返回第一个和\0的位置 string::iterator it s2.begin(); while (it ! s2.end()) {*it *;it; } cout s2 endl;//范围for循环底层也是迭代器 for (auto c : s2) {cout c endl; } 迭代器会根据迭代方向和迭代对象是否为const类型进行一些变化。反向迭代器开始位置为rbegin终止位置为rend在迭代过程中使用reverse_iterator变量并且以来迭代。const迭代器则是需要const_iterator变量。 void Test1() {//迭代器正向、反向、const、非conststring s1(hello world);//正向非const迭代器string::iterator it s1.begin();while (it ! s1.end()){cout *it ;it;}cout endl;//反向非const迭代器string::reverse_iterator rit s1.rbegin();while (rit ! s1.rend()){cout *rit ;rit; //注意是}cout endl;const string s2(hello world);//正向const迭代器string::const_iterator c_it s2.begin();while (c_it ! s2.end()){cout *c_it ;c_it;}cout endl;//反向const迭代器string::const_reverse_iterator c_rit s2.rbegin();while (c_rit ! s2.rend()){cout *c_rit ;c_rit;}cout endl; } 模拟实现 对于迭代器不同的容器使用的方法是不同的。在string类中采取了类似于指针的方式完成迭代器其实际实现可能不是指针但是使用指针也可以达到相似的迭代效果所以我们使用指针模拟一个迭代器。 //非const迭代器 typedef char* iterator; iterator begin() {return _str; } iterator end() {return _str _size; } //const迭代器 typedef const char* const_iterator; const_iterator begin() const {return _str; } const_iterator end() const {return _str _size; } 4.赋值操作 4.1 赋值重载函数 赋值重载函数也有多个重载形式支持使用string对象、c字符串和字符进行赋值。注意的一点是赋值是会覆盖原字符串的。 void Test2() {//string(1):        string operator (const string str);//c - string(2):    string operator (const char* s);//character(3):        string operator (char c);string s1(hello);string s2;s2 s1;cout s2 endl; s2 world;cout s2 endl; s2 ;cout s2 endl;} 对以上重载形式解释 (1)用string对象赋值 (2)用C-string赋值 (3)用字符赋值。 模拟实现 由于涉及到深拷贝所以需要自己实现赋值重载函数开辟空间并将信息拷贝过来即可。 //赋值重载函数string operator(string s){char* tmp new char[s._capacity 1]; //使用一个临时字符数组开辟空间保存待拷贝的字符串strcpy(tmp, s._str);delete[] _str; //原string对象可能已有值所以需要先释放空间然后再把新开辟的带有已有字符串的空间赋值给对象_str tmp;_size s._size;_capacity s._capacity;return *this;} 4.2 assign函数 除了赋值重载操作符外string类还提供了另一个名为assign的函数同样具有赋值操作但是一般很少使用当有赋值需求时一般会用 重载。 string s1(hello world);cout s1 endl;//assign()//赋值覆盖s1.assign(hello);cout s1 endl; 5.size与capacity修改 5.1 shrink_to_fit缩容、reserve扩容 shrink_to_fit实现的是缩容操作该函数会将对象的capacity缩减至合适位置即会将capacity缩小至与size相等即所有空间都被使用的合适位置。 reserve实现的是对capacity的控制对于reserve的参数n当ncapacity的时候会进行扩容操作将容量扩展至n当ncapacity时函数不做任何动作直接返回。 string s1(Say hello to the world!); //缩容 s1.shrink_to_fit(); cout s1.capacity() endl; //扩容自动扩容 s1.reserve(40); //扩容到参数值大小当reverse参数大于capacity才会执行 cout s1.capacity() endl; 模拟实现 //reserve(size_t n):重设capacity // ncapacity:扩容 // ncapacity:不做处理 void reserve(size_t n) {if (n _capacity) //当n_capacity直接return{char* tmp new char[n 1];strcpy(tmp, _str);delete[] _str;_str tmp;_capacity n;} } 5.2 resize函数 resize函数用于修改对象的size。当参数n大于对象的size时则会将size扩大至n扩大的部分则由字符参数c来填充如果没有输入c则使用\0来填充。当参数n小于等于size时则会将字符串截断使其的size为n。 //void resize(int n,char c \0)重设字符串size大小//n size 删除//size n capacity 插入//capacity n 扩容并插入string s2(hello world);s2.resize(9);cout s2 endl;cout s2.capacity() endl;s2.resize(15,);cout s2 endl;cout s2.capacity() endl;s2.resize(20,#);cout s2 endl;cout s2.capacity() endl; 模拟实现 需要注意修改size需要时刻关注capacity的大小可以使用reserve函数来让capacity设置成为我们想要的大小。 //resize(int n,char c):// nsize:将size扩大至n扩展出的空间使用参数c进行填充// nsize:将size缩小至n直接截断原字符串void resize(size_t n, char c \0){if (n _size){reserve(n); //扩容,如果不需要扩容reserve就不会发生作用for (size_t i _size; i n; i){_str[i] c;}}_str[n] \0; //nsize就截断nsize就在末尾补\0_size n;} 5.3 clear函数 clear函数可以将字符串清空也就是设置size为0。 string s1(Say hello to the world!);//清空数据不对容量做修改s1.clear();cout s1 endl;cout s1.capacity() endl; 模拟实现 //clear:将字符串置为空void clear(){_size 0; //置空只需要将size置为0然后注意字符串以\0结尾_str[_size] \0;} 6.增删查改 6.1 string插入 6.1.1 push_back尾插字符 push_back函数支持在string对象的字符串后尾插元素注意push_back函数仅仅是尾插一个字符不支持尾插字符串。 string s1(hello world);cout s1 endl;//push_back(char c)//在字符串尾插字符s1.push_back(!);cout s1 endl; 模拟实现 //push_back尾插字符void push_back(char c){if (_size _capacity) //判断容量是否足够{reserve(_capacity 0 ? 4 : 2 * _capacity); //扩容交给reserve需要考虑capacity0的情况}_str[_size] c;_size;_str[_size] c;} 6.1.2 append尾插字符串 append函数支持尾插一个字符串而根据字符串来源的不同C中提供了很多重载形式来支持比如string对象的全部或部分尾插c字符串等。 string s1(hello world);cout s1 endl;//append()--append有许多接口//在字符串尾插字符串s1.append(have a good time);cout s1 endl; 模拟实现 //append尾插字符串void append(const char* str) //使用c_str做参数类型是const char*所以如果参数写成char*权限放大会报错{size_t len strlen(str);reserve(_size len);strcpy(_str _size, str); //strcpy会自动补一个\0_size len;} 6.1.3 操作符重载 当有尾插需求时一般更习惯使用操作符因为操作符重载多个函数后字符和字符串的尾插都可以实现而且逻辑清晰易懂代码简洁。 string s1(hello world);cout s1 endl;////尾插字符或字符串s1 !;cout s1 endl;s1 Perfect;cout s1 endl; 模拟实现 //运算符重载1.尾插字符2.尾插字符串 string operator(char c) {push_back(c);return *this; } string operator(const char* str) //使用c_str做参数类型是const char*所以如果参数写成char*权限放大会报错 {append(str);return *this; } 6.1.4 insert随机插入 除了以上所说的尾插外我们势必会面临在任意位置插入字符或字符串的需求这个时候就需要使用insert函数了。insert函数支持任意指定下标位置的字符字符串插入。 //insert()//在pos位置插入string s1(hello);s1.insert(3, *** );cout s1 endl; 模拟实现 insert模拟实现我们需要重载两个版本分别支持字符和字符串的插入。需要注意insert函数实现时下标的关系防止越界情况发生具体细节可以参考代码注释。 //insert1.在pos下标位置插入字符2.在pos下标位置插入字符串 void insert(size_t pos, char c) {assert(pos _size);if (_size _capacity) //判断容量是否足够{reserve(_capacity 0 ? 4 : 2 * _capacity); //扩容交给reserve需要考虑capacity0的情况}size_t end _size 1; //注意此处end是交换后的下标所以极端情况头插下最小为0可以用size_t//如果end_size则是交换前的下标极端情况下最小为-1所以只可以使用int类型while (end pos) //最后一次交换pos位置换到pos1位置end是交换后的下标所以大于pos即可{_str[end] _str[end - 1];--end;}_str[pos] c;_size; } void insert(size_t pos, const char* str) {assert(pos _size);size_t len strlen(str);reserve(_capacity len);size_t end _size len; //注意此处end是交换后的下标所以极端情况头插下最小为0可以用size_t//如果end_size则是交换前的下标极端情况下最小为-1所以只可以使用int类型while (end pos len - 1) //最后一次交换pos位置换到poslen的位置end是交换后的下标所以需要大于poslen-1{_str[end] _str[end - len];--end;}strncpy(_str pos, str, len);_size len; } 6.2 string删除 string字符串删除需要函数erase来完成erase会删除从pos位置开始的len个长度的字符。 我们在这里发现了参数len的缺省值为npos那么这个npos是什么呢通过查询我们发现npos实际上是string类内定义的一个静态成员变量是一个无符号整型的-1值换言之就是整型的最大值。所以我们可以理解当没有传入长度参数时使用缺省值删除2^32-1个长度的字符也就是将pos位置后的字符全部删除的意思。 string s1(hello);//在pos位置删除len长度字符串缺省pos从开头删缺省len删到结尾为止s1.erase(3, 2);cout s1 endl; 模拟实现 在实现erase之前我们也需要定义一个静态成员变量npos静态成员变量在类内声明类外定义。 //string类内 public:static const size_t npos; //声明静态成员变量npos属于整个类共享//string类外 const size_t m_string::string::npos -1; //静态成员变量在类内声明在类外定义需要注意npos的所在域命名空间m_string内的类string的静态成员npos 在完成erase时需要注意lennpos的情况因为这种情况很有可能造成我们判断的时候溢出从而产生bug。  //erase删除pos位置开始的len个字符void erase(size_t pos 0, size_t len npos){assert(pos _size);if (len _size - pos) //截断的情况//删除的末尾位置超过或就是字符串的最后一个字符lenpos_size这个表达式lenpos可能会溢出;或者剩余字符长度小于等于待删除字符长度len_size-pos不存在溢出风险{_str[pos] \0;_size pos;}else{strcpy(_str pos, _str pos len); //直接将后续字符覆盖到pos位置_size - len;}} 6.3 string替换 replace函数完成string中部分字符替换的功能使用场景不是很多只需要知道有这么一个函数支持这个功能就好。replace会将pos位置开始的len个字符替换为指定字符串。 //replace(pos, len, str)//把pos位置开始的len长度替换为str字符串s1.replace(3, 2, );cout s1 endl; 6.4 string查找 string类对于字符串查找给出了许多函数。分别支持顺序查找、倒序查找、找第一个匹配的、找最后一个匹配的、找第一个不匹配的、找最后一个不匹配的等。在这些函数中我们最应该了解的就是最纯真的find函数了。 //从前往后、从后往前找与字符串中包含的字符相匹配、不匹配的字符//size_t find_first_of (const string str, size_t pos 0) const;//size_t find_last_of (const string str, size_t pos npos) const;//size_t find_first_not_of(const string str, size_t pos 0) const;//size_t find_last_not_of (const string str, size_t pos npos) const;string s1(hello world);cout s1.find_first_of(aeiou) endl;cout s1.find_last_of(aeiou) endl;cout s1.find_first_not_of(aeiou) endl;cout s1.find_last_not_of(aeiou) endl; find函数也给出了很多查找的重载形式但是使用方式一致查找pos位置开始的字符、字符串。如果找到了就会返回对应位置的下标否则返回npos。 //size_t find(str/char, pos)//从pos位置找对应的字符串/字符找到返回下标没找到返回npossize_t pos 0;while ((pos s1.find( , pos)) ! string::npos){s1.replace(pos, 1, ##);}cout s1 endl; 模拟实现 //find寻找字符串中pos开始首个匹配的字符、子串的下标找不到就返回npos size_t find(char c, size_t pos 0) const {assert(pos _size);for (size_t i pos; i _size; i){if (_str[i] c){return i;}}return npos; } size_t find(const char* str, size_t pos 0) const {assert(pos _size);const char* tmp strstr(_str, str);if (tmp nullptr){return npos;}else{return tmp - _str;} } 6.5 字符串截取 substr函数的作用是截取字符串substr会将从pos位置开始的len长度的字符截取出来创建一个新的string对象并返回。 //size_t find (const string str / char c, size_t pos 0) const; find从pos位置开始查找指定字符串、字符返回下标//size_t rfind (const string str, size_t pos npos) const; rfind从后往前找//string substr(size_t pos 0, size_t len npos) const; 取出pos开始len长的子串string s2(abc#def#ghi);cout s2.substr(s2.find(#)) endl;cout s2.substr(s2.rfind(#)) endl; 模拟实现 //substr将pos位置开始len长度的字符串作为string对象string substr(size_t pos 0, size_t len npos){assert(pos _size);string ret;if (len _size - pos) //拷贝不到原字符串结尾,避免溢出{for (size_t i pos; i pos len; i) //拷贝到poslen{ret _str[i];}}else //拷贝剩余所有字符{for (size_t i pos; i _size; i) //拷贝到_size{ret _str[i];}}return ret;} 7.交换string对象的值 在c中string类中实现了swap函数可以通过swap函数来交换两个string对象的值。在这里不得不提的是C中有swap函数模板对于基本数据类型而言编译器会自动推导数据类型并使用模板生成对应的函数完成交换操作。而对于自定义类型则需要自己实现针对swap函数string类就自主实现了交换的操作。 但是我们知道类的成员函数的参数默认第一个是this指针而且在调用时需要使用s1.swap(s2);的方式进行调用这和我们常规的swap函数的使用方式有一些不同。所以出于方便考虑string在类外定义了一个swap函数以包裹类内的swap函数以完成swap(s1,s2);的调用方式。 模拟实现 //string类内//swap交换两个string对象void swap(string s) //swap在C中以函数模板存在所以对于自定义类型需要自主实现{std::swap(_str, s._str);std::swap(_size, s._size);std::swap(_capacity, s._capacity);}//string类外//在使用swap时一般会用swap(s1,s2)的形式所以需要再写一个swap来满足该种形式的调用void swap(string s1, string s2){s1.swap(s2);} 8.比较操作符重载 string中实现了compare成员函数进行比较但是在习惯上我们更喜欢使用比较操作符重载来完成比较操作。 比较操作符被string类重载为了类外函数这么做的目的主要是满足特殊的比较情况。因为字符串比较有可能将一个const char*类型的对象放在操作符的左边但是成员函数的第一个参数this指针必然是操作符第一个操作数因此就无法支持这种情况了所以在类外实现重载。 模拟实现 在实现比较操作符重载时我们只需要重载两个参数都是string对象的即可因为我们使用的构造函数是单参数构造函数如果使用C字符串则会存在隐式类型转换将字符串类型转化变为string对象。 //比较操作符重载因为需要支持char*和string比较所以全局重载若在类中重载那么this指针必然是第一个参数就无法支持char*在的左侧了//由于单参数构造支持隐式类型转换所以char*会变为string类型进行比较因而支持了string和char*之间的任意次序的比较bool operator(const string s1, const string s2){return strcmp(s1.c_str(), s2.c_str()) 0;}bool operator!(const string s1, const string s2){return !(strcmp(s1.c_str(), s2.c_str()) 0);}bool operator(const string s1, const string s2){return strcmp(s1.c_str(), s2.c_str()) 0;}bool operator(const string s1, const string s2){return s1 s2 || s1 s2;}bool operator(const string s1, const string s2){return !(s1 s2);}bool operator(const string s1, const string s2){return !(s1 s2);} 9.输入和输出 之前在日期类的实现中我们提到过流插入、流提取为了满足参数顺序关系所以定义在类外。 9.1 流插入 9.1.1  流插入运算符重载 模拟实现 可以使用迭代器来进行流插入。  //流插入ostream operator(ostream out, const string s){for (auto e : s) //使用迭代器遍历因为编译器支持内置类型的流插入所以直接使用就好{out e;}return out;} 9.2 流提取 9.2.1 流提取操作符重载 对于流提取操作符而言c规定遇到空格字符或换行符则标志着一次提取完成换言之遇到空格或换行就结束。 模拟实现 在实现中我们需要注意 ①流提取会覆盖原来的string对象内的数据所以需要清空再写入 ②流提取碰到空格或换行就结束同时c内的操作符读取不到空格和换行字符所以需要istream的成员函数get来读取字符 ③为了更好的提高效率我们可以构造类似于缓冲区的结构对读取的字符进行缓冲并整体写入。 //流提取遇到空格字符或换行字符就结束 istream operator(istream in, string s) {s.clear(); //流提取是覆盖原数据所以需要先清空char buff[128];size_t cou 0;char c;//in c; //C规定流提取自动忽略空格字符和换行字符c in.get(); //使用istream类的成员函数get来读取字符while (c ! c ! \n) //当没有读到空格字符和换行字符时就继续{//s c; //一个字符一个字符的尾插效率不高//使用一个buff数组当做缓冲区当缓冲区满了之后一并尾插提高效率buff[cou] c;if (cou 127){buff[cou] \0;s buff;cou 0;}c in.get();}if (cou 0) //最后缓冲数组还有数据则全部尾插{buff[cou] \0;s buff;}return in; } 9.2.2 getline函数 与流提取操作符不同getline会读取一行数据即会读取空格遇到换行才会停止。 模拟实现 getline和操作符实现只在判断读取终点的时候有所不同其余部分思路代码一致。 //getline只在遇到换行字符结束 // 和流插入只在while判断处不同 istream getline(istream in, string s) {s.clear();char buff[128];size_t cou 0;char c;c in.get();while (c ! \n) //没有读到换行字符时就继续{buff[cou] c;if (cou 127){buff[cou] \0;s buff;cou 0;}c in.get();}if (cou 0){buff[cou] \0;s buff;}return in; } 10.拷贝构造函数、赋值重载运算符的改进 对于拷贝构造和赋值重载运算符我们的策略是对string对象中的每个成员变量进行拷贝复制。但是如果面对成员变量很多的对象这种方法就会造成代码的增加写起来会很麻烦。所以我们可以考虑函数复用的方式来减少我们所需要写的代码。 在实现复用前我们需要强调①局部对象在出函数后会自动销毁②传引用传参时不会进行拷贝而传对象传参则会调用拷贝函数创建一个函数内的局部变量。 拷贝构造函数 //string(const string s) //string对象中有_str需要深拷贝 //{ // _str new char[s._capacity 1]; // strcpy(_str, s._str); // _capacity s._capacity; // _size s._size; //} //拷贝构造函数——函数复用 string(const string s) {string tmp(s._str);swap(tmp);//创建临时变量tmp交换tmp和*this这样*this就完成了拷贝同时出函数后指向空的对象tmp会被销毁 } 拷贝构造函数可以通过调用构造函数创建一个和参数一样的局部变量然后将这个局部变量交给this指针而把this指针的值交给局部变量这样就可以将创建的对象带回了。 赋值重载函数 //string operator(string s) //{ // char* tmp new char[s._capacity 1]; //使用一个临时字符数组开辟空间保存待拷贝的字符串 // strcpy(tmp, s._str);// delete[] _str; //原string对象可能已有值所以需要先释放空间然后再把新开辟的带有已有字符串的空间赋值给对象 // _str tmp; // _size s._size; // _capacity s._capacity; // // return *this; //} 赋值重载函数——函数复用1 //string operator(string s) //{ // string tmp(s); // swap(tmp);// return *this; // //拷贝构造创建临时对象tmp然后和this交换this就是和s相同的对象而tmp在出作用域就销毁 //} //赋值重载函数——函数复用2 string operator(string tmp) {swap(tmp);return *this;//函数传参传了对象所以会默认调用一次拷贝构造构造tmp然后交换tmp和this出了函数就会销毁tmp } 赋值重载运算符也可以创造一个相同的局部变量然后和this指针交换带回而原来this指针的对象因为换给了tmp所以离开了函数就会被销毁。也可以使用传值传参的形式完成拷贝函数的调用创建局部对象。 如上的改进并不会对效率产生影响但是由于函数复用将我们所要完成的代码交给了已经实现的函数去处理可以提高我们的工作效率。
http://www.zqtcl.cn/news/214974/

相关文章:

  • 常州网站建设外包襄阳做网站的
  • 临清网站优化用jsp做网站的感想
  • 个人工作室网站网站备案 万网
  • 网络推广模板网站会员管理软件
  • 西乡塘网站建设网站建设公司的成本有哪些方面
  • 在哪里可以学习做网站西安制作公司网站的公司
  • 网站建设 更新 维护淮北矿业工程建设公司网站
  • 网站开发 平台宝应做网站
  • 网站开发开题报告广州的兼职网站建设
  • 辽宁同鑫建设网站网站后期维护费用
  • 政法网站建设有哪些不足广州网站建设信息科技有限公司
  • 营销型网站 平台海口智能建站价格
  • 网站空间过期电商网站建设比较好的
  • seo公司 彼亿营销舆情优化公司
  • diango是做网站的后端吗网页怎么做成app
  • 思勤传媒网站建设公司如何查询网站的外链
  • 网站设计思路文案范文专业手机网站建设多少钱
  • 有部分网站打不开网站服务内容怎么写
  • 百度安全网站检测好看的免费的小说网站模板
  • 锡山区住房和城乡建设局网站免费ppt模板下载简约
  • 建设银行 杭州招聘网站建设工程有限公司是干什么的
  • 做网站必须购买空间吗?3点新闻发布
  • 济南集团网站建设流程东莞做网站公司首选
  • 有需要做网站推广找我网站怎么 备案
  • 怎么把网站放到服务器上站长工具seo综合查询外部链接数量
  • 做网站上市的公司开一家公司最低注册资金
  • 仙居谁认识做网站的有哪些好的网站建设
  • 互动广告机网站建设怀集网站建设
  • 好的 做网站的软件公司pinterest app下载
  • 公司网站报价邯郸软件定制