仪器网站模板,网站页面优化包括,免费高清大图网站,换了家公司做网站如何接入备案文章目录string 类用法介绍及模拟实现一、string介绍二、string类常用接口1. string类对象的常见构造接口2.string类对象的常见容量接口3.string类对象的常见修改接口4. string类对象的常见访问及遍历接口5.string其他接口1.不常用查找接口2.字符替换3.字符串拼接4.字符串排序5…
文章目录string 类用法介绍及模拟实现一、string介绍二、string类常用接口1. string类对象的常见构造接口2.string类对象的常见容量接口3.string类对象的常见修改接口4. string类对象的常见访问及遍历接口5.string其他接口1.不常用查找接口2.字符替换3.字符串拼接4.字符串排序5.字符串比较6.细看string中某个函数接口的用法三、string类模拟实现及函数解析(1)迭代器开始起始位置返回(2)构造和拷贝函数(3)赋值重载和析构函数(4)返回重载和打印打符串(5)字符串字符个数和容量大小函数(6)字符串比较重载函数(7)字符串两类扩容函数(8)字符串插入函数和删除函数(9)字符串拼接和拼接重载函数(10)字符串交换和查找函数及清理函数(11)流插入和流提取的重载函数四、string类模拟实现代码(1)simulate_string.h(2)test.cpp(3)运行结果五、深浅拷贝及其他说明string 类用法介绍及模拟实现
一、string介绍
背景在C语言中字符串是以’\0’结尾的一些字符的集合为了操作方便C标准库中提供了一些str系列的库函数但是这些库函数与字符串是分离开的不太符合OOP的思想而且底层空间需要用户自己管理稍不留神可能还会越界访问。这时候就要用到C的string类。这样就不必担心内存是否足够、字符串长度等。 介绍string 是 C 中常用的一个类也是C标准库的重要组成部分主要用于字符串处理 。string类本不是STL的容器但是它与STL容器有着很多相似的操作。而且作为一个类出现他集成的操作函数基本能完成我们大多数情况下的需要。我们可以把它看成是C的基本数据类型。 另外还要注意这里的头文件是string,不是string.h它是C字符串头文件。
关键结论 string类是basic_string模板类的一个实例它使用char来实例化basic_string模板类 1.string是表示字符串的字符串类 2.该类的接口与常规容器的接口基本相同再添加了一些专门用来操作string的常规操作。 3. string在底层实际是basic_string模板类的别名typedef basic_stringchar, char_traits, allocatorstring。 4. 不能操作多字节或者变长字符的序列。
二、string类常用接口
1. string类对象的常见构造接口 string str生成空字符串 string s(str)生成字符串为str的复制品 string s(str,begin,strlen)将字符串str中从下标begin开始、长度为strlen的部分作为字符串初值 string s(str, len)以str前len个字符串作为字符串s的初值 string s(num ,c)生成num个c字符的字符串 string s(str, x)将字符串str中从下标x开始到字符串结束的位置作为字符串初值 string(const strings) 拷贝构造函数 string str1; //生成空字符串string str2(asdf); //生成asdf的复制品string str3(12345, 1, 4);//结果为2345string str4(012345, 5); //结果为01234string str5(6, a); //结果为aaaaaastring str6(str2, 2); //结果为dfstring s3(s2); // 拷贝构造s32.string类对象的常见容量接口 size 返回字符串有效字符长度 length 返回字符串有效字符长度 capacity返回空间总大小 empty 检测字符串释放为空串是返回true否则返回false clear清空有效字符 reserve为字符串预留空间不改变有效元素个数当reserve的参数小于 string的底层空间总大小时reserve不会改变容量大小。 resize将有效字符的个数该成n个多出的空间用字符填充不够进行扩容再初始化。删除数据容量大小不会变。如果将元素个数增多size会变可能会改变底层容量的大小。 在扩容的时候vs下是从15开始的先以二倍进行扩容一次后面都是以1.5倍进行扩容。 string s(hello nza);cout s.size() endl;//9cout s.length() endl;//9cout s.capacity() endl;//15s.clear(); // 将s中的字符串清空注意清空时只是将size清0不改变底层空间的大小cout s endl;空cout s.size() endl;//0cout s.capacity() endl;//15s.resize(10, a);//将s中有效字符个数增加到10个多出位置用a进行填充cout s.size() endl;//10cout s.capacity() endl;//15s.resize(16);// 将s中有效字符个数增加到16个多出位置用缺省值\0进行填充空间原来为15不够进行扩容cout s.size() endl;//16cout s.capacity() endl;//已扩容cout s endl;s.resize(5);// 将s中有效字符个数缩小到5个cout s.size() endl;//5cout s.capacity() endl;//31cout s endl;//aaaaastring s(aaa);s.reserve(166);//175cout s.size() endl;//3cout s.capacity() endl;//175s.reserve(50);cout s.size() endl;//3cout s.capacity() endl;//175
}
3.string类对象的常见修改接口 push_back在字符串后尾插字符c append在字符串后追加一个字符串 operator 在字符串后追加字符串str c_str返回C格式字符串 find: 在当前字符串的pos默认0索引位置开始查找子串s返回找到的位置索引. rfind从字符串pos默认npos位置开始往前找字符c返回该字符在字符串中的位置 substr在str中从pos位置开始截取n个字符然后将其返回 insert(pos,char):在指定的位置pos前插入字符char iterator erase(iterator p);删除字符串中p所指的字符 iterator erase(iterator first, iterator last):删除字符串中迭代器区间[first,last)上所有字符 string erase(size_t pos 0, size_t len npos)删除字符串中从索引位置pos开始的len个字符 string str;str.append(hello); // 在str后追加一个字符hellostr n; // 在str后追加一个字符n str za; // 在str后追加一个字符串zacout str endl;//hellonzacout str.c_str() endl; // 以C语言的方式打印hellonzastring f(string.cpp);size_t pos f.rfind(.);6string sub1(f.substr(pos, 3));cout sub1 endl;.cpstring url(http://www.nzanzanza.com/kd/kd/kd/);size_t start url.find(://);//4start 3;//变为7size_t finish url.find(/, start);//24string address url.substr(start, finish - start);cout address endl;//www.nzanzanza.com//插入一个字符string s(aaaa);s.insert(1,555);cout s endl;//a555aaastring s1(rrrr);s1.insert(0, 1, z);cout s1;//zrrrrstring s1(abc);couts1endl; // s1:abcs1.insert(s1.begin(),1);// insert(pos,char):在指定的位置pos前插入字符charcouts1endl; // s1:1abc// 尾插一个字符string s1;s1.push_back(a);s1.push_back(b);s1.push_back(c);couts1endl; // s1:abc//删除一个字符string s1 123456789;s1.erase(s1.begin()1); // 结果13456789s1.erase(s1.begin()1,s1.end()-2); // 结果189s1.erase(1,6); // 结果189
4. string类对象的常见访问及遍历接口 operator[] :返回pos位置的字符const string类对象调用 begin end:正向迭代器begin获取一个字符的迭代器 end获取最后一个字符下一个位置的迭代器 rbegin rend(反向迭代器)begin获取一个字符的迭代器 end获取最后一个字符下一个位置的迭代器 范围for C11支持更简洁的范围for的新遍历方式 string s(hello nza);// 1. foroperator[]for (size_t i 0; i s.size(); i){cout s[i];}cout endl;// 2.迭代器string::iterator it s.begin();while (it ! s.end()){cout *it ;it;}cout endl;//hellonzastring::reverse_iterator rit s.rbegin();// C11之后直接使用auto定义迭代器让编译器推到迭代器的类型//auto rits.rbegin();while (rit ! s.rend()){cout *rit ;rit;}cout endl;//aznolleh// 3.范围forfor (auto ch : s)cout ch;//hellonza5.string其他接口
1.不常用查找接口
1.size_tfind_first_of (const char* s, size_t pos 0) const在当前字符串的pos索引位置开始查找子串s的字符返回找到的位置索引-1表示查找不到字符 2.size_tfind_first_not_of (const char* s, size_t pos 0) const在当前字符串的pos索引位置开始查找第一个不位于子串s的字符返回找到的位置索引-1表示查找不到字符 3.size_t find_last_of(const char* s, size_t pos npos) const当前字符串的pos索引位置开始查找最后一个位于子串s的字符返回找到的位置索引-1表示查找不到字符 4.size_tfind_last_not_of (const char* s, size_t pos npos) const在当前字符串的pos索引位置开始查找最后一个不位于子串s的字符返回找到的位置索引-1表示查找不到子串 string s(ddd bbrb ccccccc bbrb ccc);cout s.find_first_of(mmmmbr98) endl; // 结果是4cout s.find_first_not_of(hhh ddd ) endl;// 结果是4cout s.find_last_of(13r98) endl; // 结果是19cout s.find_last_not_of(teac) endl; // 结果是21
2.字符替换
string replace(size_t pos, size_t n, const char *s);将当前字符串从pos索引开始的n个字符替换成字符串sstring replace(size_t pos, size_t n, size_t n1, char c); 将当前字符串从pos索引开始的n个字符替换成n1个字符cstring replace(iterator i1, iterator i2, const char* s);将当前字符串[i1,i2)区间中的字符串替换为字符串s string s1(hello world?);couts1.size()endl; // 结果12s1.replace(s1.size()-2,2,3,.); // 结果hello worl...s1.replace(6,5,green); // 结果hello green.// s1.begin(),s1.begin()5 是左闭右开区间s1.replace(s1.begin(),s1.begin()5,red); // 结果red green.couts1endl;3.字符串拼接
append() 操作符:拼接字符串 string s1(aaa);s1.append(bbb);couts1:s1endl; // s1:aaabbb// 方法二 操作符string s2 aaa;string s3 bbb;s2 s3.c_str();couts2endl; // s2:aaabbb
4.字符串排序
sort(s.begin(),s.end()):排序 要加#include algorithm头文件 string s cdefba;sort(s.begin(),s.end());coutsendl; // 结果abcdef5.字符串比较
C 字符串支持常见的比较操作符,,,,,!两个字符串自左向右逐个字符相比按ASCII值大小相比较直到出现不同的字符或遇’\0’为止。 cout (string(1) string(4)) endl;//打印为1string str1(666);string str2(222);bool ret;ret str1 str2;cout ret endl; // 1str1 111;ret str1 str2;cout ret endl; // 0str1 111;ret str1 str2;cout ret endl;//1string s1(fds);cout (s1 few) endl;//1第二种用成员函数compare()。支持多参数处理用索引值和长度定位子串来进行比较。 他返回一个整数来表示比较结果1表示大于 -1表示小于 0表示相等。 string A(dag);string B(cvb);string C(2111);string D(9850);cout A.compare(B) endl; // dag和cvbv比较 打印为1cout A.compare(1, 1, B) endl;// 拿A的第一个位置起一个字符和B比较 结果-1cout C.compare(0, 3, D, 0, 3) endl;//C第0位置前三个字符211和D前三个字符985比较结果为-16.细看string中某个函数接口的用法
可登录www.cplusplus.com查看
三、string类模拟实现及函数解析
(1)迭代器开始起始位置返回 typedef char* iterator;typedef const char* const_iterator;iterator begin(){return _str;}iterator end(){return _str _size;}const_iterator begin() const{return _str;}const_iterator end() const{return _str _size;}开始直接返回首元素地址结束返回的是最后一个元素的下一个位置的地址另外迭代器还有const类型的与它构成函数重载。
(2)构造和拷贝函数 string(const char* str ):_size(strlen(str)){_capacity _size 0 ? 3 : _size;_str new char[_capacity 1];strcpy(_str, str);}string(const string s):_size(s._size), _capacity(s._capacity){_str new char[s._capacity 1];strcpy(_str, s._str);}1、构造函数在构造函数里面传常量那么私有域里面的_str就要加const就变成在常量区这样_str就不允许修改扩容也不扩不了而这里还需要修改内容不够还需要扩容所以最好空间是new出来的从堆上申请出来的。 2、现在初始化列表就初始化一个_size,因为初始化列表是按private里面的顺序进行初始化私有域一修改可能会出现问题而且用多了strlen会造成时间浪费所以后面的开空间和_capacity初始化操作放在里面。capacity1存的是有效字符。 3、里面并给缺省值这里面不能给空指针strlen会对它进行解引用会崩溃遇到\0终止也不能’\0‘,类型不匹配char转变成了int也会当成空指针还是一个崩溃正确写法\0,这是一个常量字符串遇到\0终止长度为0或者写成 因为默认都是以\0结束的。 4、拷贝构造函数如果是默认生成是浅拷贝如果涉及空间问题就得手动写因为会指向同一个空间析构两次会崩溃修改还会互相影响。所以要有独立的空间先把size和capacity放在初始化列表里面开一个和是s.capacity一样大的空间最后strcpy。
(3)赋值重载和析构函数 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(){delete[] _str;_str nullptr;_size _capacity 0;}1、赋值重载赋值同样会涉及到深拷贝和浅拷贝问题如果被赋值的空间比要赋值的空间大赋值过去前者另外的空间会浪费掉那就先开一个和后者一样大的临时空间再把旧空间(前者)释放掉再把开的空间赋值给前者这样还间接解决了如果被赋值的空间比要赋值的空间小的问题。还有一个问题自己给自己赋值会出现随机值因为旧空间释放掉了会变成随机值所以加一个if判断语句如果相等直接返回this。(而且因new失败而破坏旧空间需要把delete放到new后面)。 2、析构函数先释放_str,并把它置为空并把size和capacity置为0。
(4)返回重载和打印打符串 const char* c_str(){return _str;}const char operator[](size_t pos) const{assert(pos _size);return _str[pos];}char operator[](size_t pos){assert(pos _size);return _str[pos];}1、打印字符串直接返回首地址进行打印。 2、返回值重载为了能让实例化的对象进行[]访问元素进行赋值重载为了防止越界需要断言一下返回_str数组对应的下标元素。为了适应传来的const对象并能够进行顺利返回需要进行函数重载。
(5)字符串字符个数和容量大小函数 size_t size() const{return _size;}size_t capacity() const{return _capacity;}1、字符个数直接返回_size因为实例化对象调用构造函数就算出来_size。 2、容量大小同理。
(6)字符串比较重载函数 bool operator(const string s) const{return strcmp(_str, s._str) 0;}bool operator(const string s) const{return strcmp(_str, s._str) 0;}bool operator(const string s) const{return *this s || s *this;}bool operator(const string s) const{return !(*this s);}bool operator(const string s) const{return !(*this s);}bool operator!(const string s) const{return !(*this s);}1、字符串比较重载函数 为了能让对象进行比较进行比较重载先写出两个,里面直接调用strcmp其余的进行复用。
(7)字符串两类扩容函数 void resize(size_t n, char ch \0){if (n _size){// 删除数据--保留前n个_size n;_str[_size] \0;}else if (n _size){if (n _capacity){reserve(n);}size_t i _size;while (i n){_str[i] ch;i;}_size n;_str[_size] \0;}}void reserve(size_t n){if (n _capacity){char* tmp new char[n 1];strcpy(tmp, _str);delete[] _str;_str tmp;_capacity n;}}1、resize扩容函数它的特点是开空间初始化size会随传入的n的大小而变化如果是当前的_size会删除数据反之会补充剩余的字符。用一个if esle语句去解决如果小于就把_size更新成n并把最后一个位置置为0else里面需要看是否扩容如果需要直接复用reserve反之用while循环进行插入最后更新_size。 2、reserve扩容函数 它的特点是提前开好空间size不会变如果传入的n大于当前容量就异地扩开辟另一个空间把_str的内容赋值过去再释放掉_str,然后把tmp重新赋给_str,再更新容量。
(8)字符串插入函数和删除函数 void push_back(char ch){/*if (_size 1 _capacity){reserve(_capacity * 2);}_str[_size] ch;_size;_str[_size] \0;*/insert(_size, ch);}void push_back(const char* str){insert(_size, str);}string insert(size_t pos, char ch){assert(pos _size);if (_size 1 _capacity){reserve(2 * _capacity);}size_t end _size 1;while (end pos){_str[end] _str[end - 1];--end;}_str[pos] ch;_size;return *this;}string insert(size_t pos, const char* str){assert(pos _size);size_t len strlen(str);if (_size len _capacity){reserve(_size len);}// 挪动数据size_t end _size len;while (end pos len - 1){_str[end] _str[end - len];--end;}// 拷贝插入strncpy(_str pos, str, len);_size len;return *this;}string erase(size_t pos, size_t len npos){assert(pos _size);if (len npos || pos len _size){_str[pos] \0;_size pos;}else{strcpy(_str pos, _str pos len);_size - len;}return *this;}
1、**push_back函数**尾插插入用常规思路去写如果需要扩容就reserve反之就进行尾插赋值最后一个位置置为\0。 第二种就复用insert因为它是在pos位置前面插入所以只需要传最后一个位置的参数即可也就是在\0前面插入就形成了尾插效果。另外为了方便进行字符串尾插进行函数重载一下即可。 2、insert函数 插入字符先看是否能扩容接下来就是挪动一般是从最后一个位置开始挪动加上while(endpos)条件可结果出错这里的end是无符号无符号end再–减到-1被当成全1是无符号最大值造成错误同样这里也不能改成int因为会发生隐式转换有符号变成无符号除非上面参数pos也改成int就能解决或者把pos强转int。但是这是模拟实现下标都常用无符号。 解决可以把end位置往后挪一位也即从最后一个位置的下一个位置开始挪动。把end-1的数赋给end这样end等于pos的时候就停止而且第一个位置也已经被挪动。就能成功运行。再进行赋值并更新_size。 插入字符串 大致思路和上面一样注意的是终止条件并不是pos位置如果是pos位置的话会发生越界因为字符串已经挪完end还没有到posend是从endlen的位置开始的。所以这里应该是挪完的时候在poslen停的位置就再减一。最后空出的位置直接进行字符串拷贝更新_size。 3、erase函数 删除分为两种情况一种是poslen长度大于等于size意思是把pos位置之后的全删掉那就把pos位置置为\0在更新_size。 第二种是长度小于size就把后面的数据往前挪动可以用拷贝函数进行从前往后覆盖直接注意的是len npos要单独写否则会溢出因为如果n是npos已经是最大值了再加就会绕回去所以防止用缺省值和pos相加出错分开来写。
(9)字符串拼接和拼接重载函数 void append(const char* str){//size_t len strlen(str);//if (_sizelen _capacity)//{// reserve(_size len);//}strcat(_str, str);//_size len;insert(_size, str);}string operator(char ch){push_back(ch);return *this;}string operator(const char* str){push_back(str);//append(str);return *this;}1、append拼接函数两种方法一种是算长度看是否要扩容然后直接调用字符串追加函数strcat进行追加另一种是复用insert。 2、拼接重载函数字符重载函数直接复用push_back字符串重载函数复用append和push_back都可行。
(10)字符串交换和查找函数及清理函数 void swap(string s){std::swap(_str, s._str);std::swap(_capacity, s._capacity);std::swap(_size, s._size);}size_t find(char ch, size_t pos 0){assert(pos _size);for (size_t i pos; i _size; i){if (_str[i] ch){return i;}}return npos;}size_t find(const char* str, size_t pos 0){assert(pos _size);char* p strstr(_str pos, str);if (p nullptr){return npos;}else{return p - _str;}}void zero(){_str[0] \0;_size 0;}1、交换函数 string库里面的交换函数是void swap(string x, string y)里面需要创建临时变量进行赋值发生了三次深拷贝而这模拟实现可以是void swap(string s)在里面调用C标准库里面的swap把三个成员换一下就可以效率可以提升很多。 2、查找函数对于字符查找函数用for循环进行遍历如果找了就返回下标否则返回npos。 对于字符串查找函数直接调用子串搜索函数并返回它的首地址如果找不到返回npos否则返回它的地址减去首地址。 3、清0函数把size的位置置为\0并把size置为0和流插入函数结合用。
(11)流插入和流提取的重载函数
ostream operator(ostream out, const string s)
{for (auto ch : s){out ch;}return out;
}
istream operator(istream in, string s)
{s.zero();char ch in.get();char tmp[128];size_t i 0;while (ch ! ch ! \n){tmp[i] ch;if (i 127){tmp[127] \0;s tmp;i 0;}ch in.get();}if (i ! 0){tmp[i] \0;s tmp;}return in;
}
这两个函数不能写到里成员函数因为this指针就把第一个位置抢了cout做不了第一个左操作数得写成全局不一定要用友元函数。 流插入函数 直接couts和coutc_str有区别后者遇到\0停止里面直接用for循环进行打印。 流提取函数1、C/C规定输入多个字符会把\n和空格当成多个字符之间的间隔cin流对象缓冲区会拿不到\n和空格,用get就不会把它两当成间隔把它们拿到wihle就能终止。 2、流提取前要清理一下设置\0防止出现乱码。 3、如果插入的字符串很长啊会频繁扩容先创建一个tmp临时数组输入一个字符填到数组里如果快要填满的时候就在最后填上\0把这个数组加到s上去i置为0。每满一次往s上加。如果最后i不等于0就直接就把tmp i的位置置为\0最后还要判断一下i是否为0如果不为0说明tmp里面还没有加进去完。
四、string类模拟实现代码
(1)simulate_string.h
#pragma once
#includeassert.h
namespace mould
{class string{public:typedef char* iterator;typedef const char* const_iterator;iterator begin(){return _str;}iterator end(){return _str _size;}const_iterator begin() const{return _str;}const_iterator end() const{return _str _size;}string(const char* str ):_size(strlen(str)){_capacity _size 0 ? 3 : _size;_str new char[_capacity 1];strcpy(_str, str);}string(const string s):_size(s._size), _capacity(s._capacity){_str new char[s._capacity 1];strcpy(_str, s._str);}// s1 s3;// s1 s1;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(){delete[] _str;_str nullptr;_size _capacity 0;}const char* c_str(){return _str;}const char operator[](size_t pos) const{assert(pos _size);return _str[pos];}char operator[](size_t pos){assert(pos _size);return _str[pos];}size_t size() const{return _size;}size_t capacity() const{return _capacity;}// 不修改成员变量数据的函数最好都加上constbool operator(const string s) const{return strcmp(_str, s._str) 0;}bool operator(const string s) const{return strcmp(_str, s._str) 0;}bool operator(const string s) const{return *this s || s *this;}bool operator(const string s) const{return !(*this s);}bool operator(const string s) const{return !(*this s);}bool operator!(const string s) const{return !(*this s);}void resize(size_t n, char ch \0){if (n _size){// 删除数据--保留前n个_size n;_str[_size] \0;}else if (n _size){if (n _capacity){reserve(n);}size_t i _size;while (i n){_str[i] ch;i;}_size n;_str[_size] \0;}}void reserve(size_t n){if (n _capacity){char* tmp new char[n 1];strcpy(tmp, _str);delete[] _str;_str tmp;_capacity n;}}void push_back(char ch){insert(_size, ch);}void push_back(const char* str){insert(_size, str);}void append(const char* str){insert(_size, str);}string operator(char ch){push_back(ch);return *this;}string operator(const char* str){append(str);return *this;}string insert(size_t pos, char ch){assert(pos _size);if (_size 1 _capacity){reserve(2 * _capacity);}size_t end _size 1;while (end pos){_str[end] _str[end - 1];--end;}_str[pos] ch;_size;return *this;}string insert(size_t pos, const char* str){assert(pos _size);size_t len strlen(str);if (_size len _capacity){reserve(_size len);}// 挪动数据size_t end _size len;while (end pos len - 1){_str[end] _str[end - len];--end;}// 拷贝插入strncpy(_str pos, str, len);_size len;return *this;}string erase(size_t pos, size_t len npos){assert(pos _size);if (len npos || pos len _size){_str[pos] \0;_size pos;}else{strcpy(_str pos, _str pos len);_size - len;}return *this;}void swap(string s){std::swap(_str, s._str);std::swap(_capacity, s._capacity);std::swap(_size, s._size);}size_t find(char ch, size_t pos 0){assert(pos _size);for (size_t i pos; i _size; i){if (_str[i] ch){return i;}}return npos;}size_t find(const char* str, size_t pos 0){assert(pos _size);// kmpchar* p strstr(_str pos, str);if (p nullptr){return npos;}else{return p - _str;}}void zero(){_str[0] \0;_size 0;}private:char* _str;size_t _capacity;size_t _size;static const size_t npos;};const size_t mould::string::npos -1;
}
(2)test.cpp
#includeiostream
#includesimulate_string.h
using namespace std;
void Print(const mould:: string s)
{for (size_t i 0; i s.size(); i){cout s[i] ;}cout endl;mould::string::const_iterator it s.begin();while (it ! s.end()){//*it x;it;}for (auto ch : s){cout ch ;}
}
ostream operator(ostream out, const string s)
{for (auto ch : s){out ch;}return out;
}
istream operator(istream in, string s)
{s.clear();char ch in.get();char tmp[128];size_t i 0;while (ch ! ch ! \n){tmp[i] ch;if (i 127){tmp[127] \0;s tmp;i 0;}ch in.get();}if (i ! 0){tmp[i] \0;s tmp;}return in;
}void _string1()
{mould::string s1(power latent);cout s1.c_str() endl;s1[0];cout s1.c_str() endl;cout endl;
}
void _string2()
{mould::string s2(power latent);mould::string s3(s2);mould::string s1;cout s2.c_str() endl;cout s3.c_str() endl;s2[0];cout s2.c_str() endl;cout s3.c_str() endl;s1 s2;cout s1.c_str() endl;cout s2.c_str() endl;cout endl;}
void _string3()
{mould::string s1(power latent);for (size_t i 0; i s1.size(); i){s1[i];}for (size_t i 0; i s1.size(); i){cout s1[i];}cout endl;Print(s1);mould::string::iterator it s1.begin();while (it ! s1.end()){(*it)--;it;}cout endl;it s1.begin();while (it ! s1.end()){cout *it ;it;}cout endl;for (auto ch : s1){cout ch ;}cout endl;cout endl;}
void _string4()
{mould::string s1(power latent);mould::string s2(power latent);mould::string s3(aa);cout (s1 s2) endl;cout (s1 s2) endl;cout (s1 s2) endl;cout endl;
}void _string5()
{mould::string s1(power latent);s1 ;s1 ssssssssssssssssssssssssssss;cout s1.c_str() endl;s1.insert(6, c);cout s1.c_str() endl;s1.insert(0, q);cout s1.c_str() endl;cout endl;
}void _string6()
{mould::string s1(hello world66666666666);cout s1.capacity() endl;s1.reserve(10);cout s1.capacity() endl;cout endl;
}
void _string7()
{mould::string s1;s1.resize(10, k);cout s1.c_str() endl;s1.resize(15, d);cout s1.c_str() endl;s1.resize(3);cout s1.c_str() endl;cout endl;
}
void _string8()
{mould::string s1(6666666);s1.insert(0, a);cout s1.c_str() endl;s1.insert(2, a);cout s1.c_str() endl;s1.insert(3, bbb);cout s1.c_str() endl;s1.insert(1, bbb);cout s1.c_str() endl;cout endl;
}
void _string9()
{mould::string s1(0123456789);cout s1.c_str() endl;s1.erase(4, 3);cout s1.c_str() endl;s1.erase(4, 30);cout s1.c_str() endl;s1.erase(2);cout s1.c_str() endl;cout endl;
}
void _string10()
{string s1(0123456789);s1 \0;s1 xxxxxxxx;couts1endl ;couts1.c_str() endl;string s2;cins2;couts2 endl;cins1;couts1 endl;
}int main()
{_string1();_string2();_string3();_string4();_string5();_string6();_string7();_string8();_string9();_string10();return 0;
}(3)运行结果 五、深浅拷贝及其他说明
浅拷贝也叫位拷贝编译器只是将对象中的值拷贝过来。如果对象中管理资源最后就会导致多个对象共享同一份资源当一个对象销毁时就会将该资源释放掉而此时另一些对象不知道该资源已经被释放以为还在所以当继续对资源进项操作时就会发生发生了非法访问。 深拷贝可以用深拷贝解决浅拷贝问题每个对象都有一份独立的资源不要和其他对象共享如果一个类中涉及到资源的管理其拷贝构造函数、赋值运算符重载以及析构函数必须要显式给出。保证多个对象不会因共享资源造成多次释放造成程序崩溃问题。 vs下string的结构 string总共占28个字节内部结构复杂。 1、先是有一个联合体联合体用来定义string中字符串的存储空间当字符串长度小于16时使用内部固定的字符数组来存放当字符串长度大于等于16时从堆上开辟空间。 2、Mysize存字符串有效长度。 3、Myres存空间容量。 4、还有一个指针。 g下string的结构g下string是通过写时拷贝实现的string对象总共占4个字节(64位下是8个字节)内部只包含了一个指针该指针将来指向一块堆空间内部包含了如下字段 1、空间总大小 2、字符串有效长度 3、引用计数