
目录string 的介绍1. 什么是 C string2. 基本用法3. 常用操作3.1 长度与判空3.2 拼接与追加3.3 访问字符3.4 查找与子串3.5 插入与删除4. 与 C 风格字符串的转换常用函数介绍1. string 的成员变量简单 重要2. 构造函数 析构函数 拷贝构造函数重要3. string类对象的容量操作size() 和 length() 函数介绍简单 size重要 length了解即可capacity函数介绍熟悉即可empty() 和 clear() 函数介绍重要比较低 简单reserve() 函数介绍重要resize() 函数介绍重要4.string类对象的访问及遍历操作c_str() 和 operator[] 函数介绍简单 重要迭代器 begin()、end()、rbegin()、rend() 介绍重要5. string类对象的修改操作push_back() 函数介绍了解operator 运算符重载介绍重要append() 函数介绍做了解即可find() rfind() 函数介绍find 重要 rfind 了解即可6. string类非成员函数 运算符重载重要getline 比较重要string 和 char* 的比较 运算符重载 重要string 的介绍1. 什么是 C string在 C 中std::string是标准库提供的字符串类定义在头文件string中。它封装了字符序列的存储和管理大部分我们所需常用的功能都可以在std::string相比 C 语言中以\0结尾的字符数组在C语言中相对想要操控字符串删改内容等都需要自己进行函数进行函数搭建等比较麻烦std::string使用起来更安全、更方便能够自动管理内存并提供了丰富的成员函数用于字符串的拼接、查找、替换、比较等操作。2. 基本用法使用std::string前需要包含头文件并引入命名空间#include iostream #include string using namespace std; int main() { // 多种初始化方式 string s1; // 空字符串 string s2 hello; // 拷贝初始化 string s3(world); // 直接初始化 string s4(5, a); // aaaaa string s5 s2 s3; // 拼接 cout lt;lt; s5 lt;lt; endl; // 输出 hello world return 0; }3. 常用操作下面介绍std::string最常用的几类操作。3.1 长度与判空string s hello; size_t len s.size(); // 5size() 和 length() 等价 bool empty s.empty(); // false3.2 拼接与追加string s hello; s world; // 使用 追加 s.append(!); // 或使用 append s.push_back(?); // 追加单个字符3.3 访问字符string s hello; char c1 s[0]; // 下标访问不检查越界 char c2 s.at(1); // 越界会抛出 out_of_range 异常 s[0] H; // 修改字符3.4 查找与子串string s hello world; size_t pos s.find(world); // 返回 6找不到返回 string::npos string sub s.substr(6, 5); // 从下标 6 开始取 5 个字符得到 world3.5 插入与删除string s hello; s.insert(5, world); // 在下标 5 处插入 s.erase(5, 6); // 从下标 5 开始删除 6 个字符恢复为 hello s.clear(); // 清空字符串4. 与 C 风格字符串的转换在调用某些 C 语言接口时需要将std::string转换为const char*可以使用c_str()方法string s hello; const char* cstr s.c_str(); // 得到以 \0 结尾的 C 字符串 // 反过来C 字符串可以直接赋值给 string string s2 cstr;常用函数介绍学习建议string 的功能多复杂掌握最常用的几个函数功能即可如果出现陌生的函数就网上找即可一般考试只需要掌握最常用的20来个即可工作需要的也20来个也是够用就可以如果出现陌生的网上找即可最好是预先熟悉各个函数的功能并且练习打代码即可只读功能放回值参数等默写打出来即可深刻熟悉代码。自己练习可以用命名空间包装起来把代码包装起来与 std::string 标准库作对比。做三份文件 一个string.h 头文件 string.cpp 代码文件 test.cpp 测试文件1. string 的成员变量简单 重要class string { private: char* _str; //存放字符串的位置 size_t _size;//有效字符个数 size_t _capacity;//实际可存取最大空间数量 public: static const size_t npos;// 其他用于找不到等其他功能变量 通常 取 -1 (size_t 无符号的原因会变得非常大) };char* _str; //存放字符串的位置size_t _size;//有效字符个数size_t _capacity;//实际可存取最大空间数量2. 构造函数 析构函数 拷贝构造函数重要using namespace Youren; //npos const size_t string::npos -1; //构造 string::string(const char* str) :_size(strlen(str)) { _str new char[_size 1]; _capacity _size; strcpy(_str, str); } string::string(const string str) { _size str._size; _capacity str._capacity; _str new char[_capacity 1]; strcpy(_str, str._str); } //析构 string::~string() { delete[] _str; _size 0; _capacity 0; }构造步骤_str 申请空间复制_size 和_capacity 的赋值析构步骤delete[] _str , _size 和 _capacity 赋值为0注意npos 需要记得赋值 -1 往后代码都需要用到申请空间都需要预留多一个空间存取\0位置capacity 无需一起13. string类对象的容量操作//* 表示重要程度 size_t size() const;//** size_t length()const; size_t capacity()const;//** bool empty()const;//* void clear();//** void reserve(const size_t new_capacity);//*** void resize(const size_t count);//** void resize(const size_t count, char ch);//**size() 和 length() 函数介绍简单 size重要 length了解即可两者的都是一样的经常用的 size 在类内比较少用但是在类外想要知道私有的 _size 大小就需要 size() 。功能返回 _size 大小size_t string::size() const { return _size; } size_t string::length()const { return _size; }capacity函数介绍熟悉即可功能返回_capacity;size_t string::capacity()const { return _capacity; }empty() 和 clear() 函数介绍重要比较低 简单功能empty 判断str 是否为空字符串什么方式都可以_size0 _str[0]\0clear 清理为空字符串_capacity 保存不变bool string::empty()const { assert(_str ! nullptr); return *_str \0; } void string::clear() { _str[0] \0; _size 0; return; }reserve() 函数介绍重要void reserve(const size_t new_capacity);功能 扩容 根据 new_capaity 与原有的_capacity 比较需不需要扩容注意点不能无脑 _capacity * 2 还需new_capacity 进行比较 多预留一个空间存放‘\0’。void string::reserve(const size_t new_capacity) { if (_capacity new_capacity) { return; } //扩容两倍 生成新空间 新空间内容拷贝 旧空间回收 _str承接str新空间 _capacity _capacity * 2 new_capacity ? _capacity * 2 : new_capacity; char* str new char[_capacity 1];//一定要 1 预留‘\0’ memcpy(str, _str, _size 1); delete[] _str; _str str; }resize() 函数介绍重要void resize(const size_t count); void resize(const size_t count, char ch);功能只传参 count 修改 size count 小于 size 就对于位置 str 进行赋值‘\0’ ,并且赋值 size count count 大于 size 就需要对相对多出来的位置进行‘\0’ 赋值操作如果传参再加上 ch相对多出来的位置进行 ch 赋值操作。注意点还是末尾\0问题。void string::resize(const size_t count) { //count _size if (count _size) { _str[count] \0; _size count; } else { reserve(count); for (size_t i _size; i count; i) { _str[i] \0; } _size count; } return; } void string::resize(const size_t count, const char ch) { //count _size if (count _size) { _str[count] \0; _size count; } else { reserve(count); for (size_t i _size; i count; i) { _str[i] ch; } _str[count] \0; _size count; } return; }4.string类对象的访问及遍历操作//string类对象的访问及遍历操作 const char* c_str() const; //** const char operator[](size_t i) const; char operator[](size_t i); //迭代器 begin rbegin end rend //for(auto ch : str)c_str() 和 operator[] 函数介绍简单 重要const char* c_str() const; //** const char operator[](size_t i) const; char operator[](size_t i);功能c_str() 返回 _str 的首元素地址operator[] 返回对应_str 的地址位置//取地址地址 const char string::operator[](size_t i) const { assert(i _size); return _str[i]; } const char* string::c_str() const { return _str; } char string::operator[](size_t i) { assert(i _size); return _str[i]; }迭代器 begin()、end()、rbegin()、rend() 介绍重要迭代器是 STL 中用于遍历容器元素的对象可以把它理解为「指向元素的指针」。string 提供了正向迭代器和反向迭代器分别用于从前往后和从后往前遍历字符串。一般迭代器不用定义分离只需要在头文件里面写入即可。四个迭代器接口begin()返回指向第一个字符的正向迭代器。end()返回指向最后一个字符之后位置的正向迭代器不指向有效字符通常作为遍历结束标志。rbegin()返回指向最后一个字符的反向迭代器。rend()返回指向第一个字符之前位置的反向迭代器同样不指向有效字符。总结 begin rend 0 rbegin end _size ;功能通过begin()和end()可以正向遍历整个字符串通过rbegin()和rend()可以反向遍历整个字符串迭代器支持、--、*解引用等操作用法与指针类似。//迭代器 begin rbegin end rend typedef const char* const_iterator; typedef char* iterator; //for(auto ch : str) iterator begin() { return _str; } const_iterator begin()const { return _str; } iterator rbegin() { return _str _size; } const_iterator rbegin()const{ return _str _size; } iterator end() { return _str _size; } const_iterator end()const { return _str _size; } iterator rend() { return _str; } const_iterator rend()const { return _str; }注意点end()和rend()指向的是「哨兵位置」不能对其解引用只能用于比较判断是否遍历结束反向迭代器是向字符串开头方向移动--是向末尾方向移动在 C11 之后推荐直接使用范围 for 循环或auto简化迭代器书写。for 和 auto 的实际运用// test.cpp #define _CRT_SECURE_NO_WARNINGS using namespace std; #include Youren_string.h void test1() { //test iterator begin and end Youren::string str1 hello world!; for (auto ch : str1) { cout ch ; } coutendl; //tuee } int main() { test1(); return 0; }5. string类对象的修改操作//string类对象的修改操作 // 做了解即可 void push_back(char c); // 非常重要 string operator(char c); string operator(const string str); string operator(const char* s); ///const char* c_str() const; //了解即可 // C98 string append(const string str); //直接尾插 string append(const char* s); //直接尾插 string append(const char* s, size_t n); //s 拷贝字符串 n 拷贝长度 string append(size_t n, char c); //n 拷贝次数 c 字符 string append(const string str, size_t subpos, size_t sublen); //subpos str 的起始拷贝位置sublen 拷贝数量 // 非常重要 size_t find(const string str, size_t pos 0) const; size_t find(const char* s, size_t pos 0) const; size_t find(const char* s, size_t pos, size_t n) const; size_t find(char c, size_t pos 0) const; //pos 都统一都是起始开始找的位置 n 是 s 的长度 // 做了解即可 size_t rfind(const string str, size_t pos npos) const; size_t rfind(const char* s, size_t pos npos) const; size_t rfind(const char* s, size_t pos, size_t n) const; size_t rfind(char c, size_t pos npos) const; //这里rfind 的pos 的意思相反是用于查询寻位置的末位置 标准pos 的位置还是会继续访问一下但除了 npos 位置push_back() 函数介绍了解void push_back(char c);功能: 尾插一个字符void string::push_back(char c) { //判断扩容需要 尾插入字符 记得吧‘\0’再次补进去 //注意 _str[_size] 的位置是存放‘\0’直接替换导致该字符串没有‘\0’ reserve(_size 1); _str[_size] c; _str[_size] \0; return; }operator 运算符重载介绍重要string operator(char c); string operator(const string str); string operator(const char* s);尾插尾插字符字符串 或者 string 类类型的字符串string string::operator(char c) { //push_back 一致问题 reserve(_size 1); _str[_size] c; _str[_size] \0; return *this; } string string::operator(const string str) { reserve(_size str._size); memcpy(_str _size, str._str, str._size 1); _size str.size(); return *this; } string string::operator(const char* s) { size_t s_len strlen(s); reserve(_size s_len); memcpy(_str _size, s, s_len 1); _size (s_len); return *this; }append() 函数介绍做了解即可// C98 string append(const string str); //直接尾插 string append(const char* s); //直接尾插 string append(const char* s, size_t n); //s 拷贝字符串 n 拷贝长度 string append(size_t n, char c); //n 拷贝次数 c 字符 string append(const string str, size_t subpos, size_t sublen); //subpos str 的起始拷贝位置sublen 拷贝数量功能尾插一个 string 类类型的字符串尾插一个 char* 类型的字符串尾插一个 char* 类型的字符串并却 n 决定字符串拷贝的数量尾插 n 个 char 类型的字符尾插一个string 类类型的字符串subpos 控制拷贝 str 的起始位置 sublen 决定拷贝数量string string::append(const string str) //直接尾插 { //判断为空 if (str.empty()) { return *this; } //扩容 reserve(_size str._size); //拷贝数据 memcpy(_str[_size], str._str, str._size 1); //size 的有效数组位置进行更改 _size str._size; return *this; } string string::append(const char* s) //直接尾插 { if (s NULL || strlen(s) 0) { return *this; } size_t s_len strlen(s); //扩容 reserve(_size s_len); //拷贝数据 memcpy(_str[_size], s, s_len 1); //size 的有效数组位置进行更改 _size s_len; return *this; } string string::append(const char* s, size_t n) //s 拷贝字符串 n 拷贝长度 { if (s NULL || strlen(s) 0 || n0) { return *this; } n n strlen(s) ? strlen(s) : n; //扩容 reserve(_size n); //拷贝数据 memcpy(_str[_size], s, n ); //size 的有效数组位置进行更改 _size n; _str[_size] \0; return *this; } string string::append(size_t n, char c) //n 拷贝次数 c 字符 { if (n 0) { return *this; } //扩容 reserve(_size n); for (size_t i 0; i n; i) { _str[_size i] c; } _size n; _str[_size] \0; return *this; } string string::append(const string str, size_t subpos, size_t sublen) //subpos str 的起始拷贝位置sublen 拷贝数量 { //判断为空 if (str.empty() || subpos str._size) { return *this; } sublen str._size sublen subpos ? str._size - subpos : sublen; //扩容 reserve(_size sublen); //拷贝数据 memcpy(_str[_size], str[subpos], sublen); //size 的有效数组位置进行更改 _size sublen; return *this; }测试 testvoid test2() { // test operator Youren::string str1 hello world!; for (auto ch : str1) { cout ch; } cout str1.size() endl; cout endl; Youren::string str2 I love my mother; for (auto ch : str2) { cout ch; } cout str2.size() endl; cout endl; str1 str2; for (auto ch : str1) { cout ch; } cout str1.size() endl; cout endl; str2 !; for (auto ch : str2) { cout ch; } cout str2.size() endl; cout endl; str2 and I love my sister!; for (auto ch : str2) { cout ch; } cout str2.size() endl; cout endl; }find() rfind() 函数介绍find 重要 rfind 了解即可size_t find(const string str, size_t pos 0) const; size_t find(const char* s, size_t pos 0) const; size_t find(const char* s, size_t pos, size_t n) const; size_t find(char c, size_t pos 0) const; //pos 都统一都是起始开始找的位置 n 是 s 的长度 size_t rfind(const string str, size_t pos npos) const; size_t rfind(const char* s, size_t pos npos) const; size_t rfind(const char* s, size_t pos, size_t n) const; size_t rfind(char c, size_t pos npos) const; //这里rfind 的pos 的意思相反是用于查询寻位置的末位置 标准pos 的位置还是会继续访问一下但除了 npos 位置这两个函数只要掌握 find 即可find() 函数重要功能 查询字符串或者查询字符并且返回字符串所在 size_t 的位置而非地址位置找不到地址返回 npos 与 strstr 做区分strstr() 函数也是作为查询的作用但返回的是地址而非 size_t 的数值解题思路可以通过 strstr() 函数 和地址减地址的特性首元素地址和找到地址相减得出 size_t 位置参数相关pos 是起始寻找的位置 n 是 查找样本的长度//find pos 都统一都是起始开始找的位置 n 是 s 的长度 size_t string::find(const string str, size_t pos) const { //判断是否出现特殊情况如str 为空 和 起始位置不符合要求的 if (str.empty() || pos 0 || pos _size) { return npos; } char* pf strstr(_str[pos], str._str); if (pf nullptr) { return npos; } else { return pf - _str; } } size_t string::find(const char* s, size_t pos) const { //判断是否出现特殊情况如str 为空 和 起始位置不符合要求的 if (s nullptr || pos 0 || pos _size) { return npos; } char* pf strstr(_str[pos], s); if (pf nullptr) { return npos; } else { return pf - _str; } } size_t string::find(const char* s, size_t pos, size_t n) const { //判断是否出现特殊情况如str 为空 和 起始位置不符合要求的 if (s nullptr || pos 0 || pos _size) { return npos; } //拷贝新的字符串 char* ss new char[n 1]; memcpy(ss, s, n); ss[n] \0;//记得把 \0 补上 char* pf strstr(_str[pos], ss); delete[] ss; if (pf nullptr) { return npos; } else { return pf - _str; } } size_t string::find(char c, size_t pos) const { //判断是否出现特殊情况如str 为空 和 起始位置不符合要求的 if (c 0 || pos 0 || pos _size) { return npos; } //构造新的字符串 char* ss new char[2]{c,0}; char* pf strstr(_str[pos], ss); delete[] ss; if (pf nullptr) { return npos; } else { return pf - _str; } }rfind() 函数做了解与find 相反是倒着找 pos 就是末尾位置所以与find最大区别就是查找方式是从正查到倒查而已我们只需实现一个倒查的strstr() 函数即可实现private: char* rstrstr(const char* str,size_t pos 0) const;char* string::rstrstr(const char* str,size_t pos)const { if (str nullptr || empty()|| strlen(str) 0) { return nullptr; } size_t i _size - strlen(str),j i;//起始 str1 的起始位置 const char* ptr str;//标记str2 起始位置 int input 0;// 找到为1 找不到0 while (i ! npos i ! pos - 1 input ! 1) { // 刷新 ptr 的位置 ptr str; j i; while (_str[j]*ptr) { if (*ptr \0) { input 1; break; } } if (input) return _str[i]; i--; } return nullptr; }把原先find 的原先strstr位置全部代替并且对对应位置代码经行适配即可实现size_t string::rfind(const string str, size_t pos) const { //注意 npos 是 -1 但因为是取无符号数会变成非常大的数值 所有不能对 pos 0 处理 if (str.empty() || (pos _size pos ! npos)) { return npos; } char* pf rstrstr(str[0], pos); if (pf nullptr) { return npos; } else { return pf - _str; } } size_t string::rfind(const char* s, size_t pos) const { if (s nullptr || (pos _size pos ! npos)) { return npos; } char* pf rstrstr(s, pos); if (pf nullptr) { return npos; } else { return pf - _str; } } size_t string::rfind(const char* s, size_t pos, size_t n) const { if (s nullptr || (pos _size pos ! npos)) { return npos; } char* ss new char[n 1]; memcpy(ss, s, n); ss[n] \0; char* pf rstrstr(ss, pos); delete[] ss; if (pf nullptr) { return npos; } else { return pf - _str; } } size_t string::rfind(char c, size_t pos) const { if (c 0 || (pos _size pos ! npos)) { return npos; } char* ss new char[2] {c, 0}; char* pf rstrstr(ss, pos); if (pf nullptr) { return npos; } else { return pf - _str; } }测试 testvoid test4() { //test find rfind Youren::string str1 abcdefg; Youren::string str2 cde; ///cout str1 endl; //cout str2 endl; size_t i str1.find(c, 2); cout i endl; //2 i str1.find(c, 3); cout i endl endl; //npos i str1.find(str2, 3); cout i endl; //npos i str1.find(str2, 2); cout i endl endl; //2 i str1.find(cde, 2); cout i endl; //2 i str1.find(cde, 3); cout i endl endl; //npos i str1.rfind(c,2); cout i endl; //2 i str1.rfind(c, 3); cout i endl endl; //npos i str1.rfind(str2, 3); cout i endl; //npos i str1.rfind(str2, 2); cout i endl endl; //2 i str1.rfind(cde, 2); cout i endl; //2 i str1.rfind(cde, 3); cout i endl endl; //npos }6. string类非成员函数以下函数都针对的是类外的函数//string类非成员函数 std::istream operator(std::istream in, string str); std::ostream operator(std::ostream on, const string str); std::istream getline(std::istream in, string s); //operator relational getline 输入函数及其运算符重载重要std::istream operator(std::istream in, string str) { str.clear(); char ch in.get(); while (ch ! ch ! \n ch ! \t) { str ch; ch in.get(); } return in; } std::istream getline(std::istream in, string str,char delim \n) { str.clear(); char ch in.get(); while (ch ! delim) { str ch; ch in.get(); } return in; }cin 和 geline 与 string 的适配是通过清理 在一个一个字符加进去如果输入的字符串太长也会导致 操作反复扩容不断在申请空间导致时间过长的情况如果提前申请大量的空间又有可能导致空间的浪费解决问题就是先把字符串写入一个buff 的字符串中字符串充当缓存的作用充满就在一次性加入 string 内 让后继续反复操作直到结束结束时吧多余的继续录入 string 内。std::istream operator(std::istream in, string str) { str.clear(); // 改进版 实现解决一个一个字符加入 // 减少空间扩容的导致浪费时间 // 以及减少如果提前开空间导致内存浪费的情况 char buff[128];// buff 的作用类似缓存的功能 满了插入 string 内 int i 0; char ch in.get(); buff[i] ch; while (buff[i] ! buff[i] ! \n buff[i] ! \t) { buff[i] in.get(); if (i 127) { buff[i] \0; str buff; i 0; } ch in.get(); } if (i 0) { buff[i] \0; str buff; } return in; } std::istream getline(std::istream in, string s, char delim) { s.clear(); char buff[128]; int i 0; char ch in.get(); buff[i] ch; while (ch ! delim) { buff[i] ch; if (i 127) { buff[i] \0; s buff; i 0; } ch in.get(); } if (i 0) { buff[i] \0; s buff; } return in; } 输入简单std::ostream operator(std::ostream on, const string str) { for (size_t i 0; i str.size(); i) { on str[i]; } return on; }string 和 char* 的比较 运算符重载 重要有部分比较运算符可以在内但有些必须在类外进行定义例如 char* 在前 string在后的情况但最好的办法就是统一在外部进行类的运算符重载如果你向我一样在不小心已经把运算符重载以及写进类内那也没关系可以进行修正。实现目标从首元素进行比较能通过比较的并且符合运算符的就返回 true 不能就返回false需要实现的那些类型string string 进行比较string char* 进行比较char* string 进行比较再加上 6种运算符 ! ;所有需要定义的运算符重载需要 18 个 但无需每个都实现 像 string string 类型比较只需要实现 即可事项 6 个运算符重载。bool string::operator(const string str) const { size_t i 0; //长度不对应就无需比较了 if (_size ! str._size) return false; while (_str[i] str[i]) { if (i _size) return true; i; } return false; } bool string::operator(const string str) const { size_t i 0; if (_str[i] str[i]) { return true; } while (_str[i] str[i])// 循环前一步被与拦住true 继续循环 退出循环 false { //谁短情况 // str 短的情况 if (str._size i _size i) { return true; } // _str 短的情况 if (_size i str._size i) { return false; } i; if (_str[i] str[i]) { return true; } } return false; } bool string::operator(const string str) const { //调换位置 即可 return str *this; } bool string::operator!(const string str) const { return !(*this str); } bool string::operator(const string str) const { return !(*this str); } bool string::operator(const string str) const { return !(*this str); }像 string char* 把对应的第二个 char* 的位置修改即可需注意的是实现大于或者小于其中一个的时候就不可以用调换位置的方式进行修改我们目前是实现了 string char* 还没有实现 char* string的运算符重载所有需要进行特殊处理 判断是否相等和是否大于bool string::operator(const char* str) const { size_t i 0; if (_size ! strlen(str)) return false; while (_str[i] str[i]) { if (i _size) return true; i; } return false; } bool string::operator (const char* str) const { size_t i 0; if (_str[i] str[i]) { return true; } size_t str_len strlen(str); while (_str[i] str[i])// 循环前一步被与拦住true 继续循环 退出循环 false { //谁短情况 // str 短的情况 if (str_len i _size i) { return true; } // _str 短的情况 if (_size i str_len i) { return false; } i; if (_str[i] str[i]) { return true; } } return false; } bool string::operator(const char* str) const { if (*this str) return false; return !(*this str); } bool string::operator!(const char* str) const { return !(*this str); } bool string::operator(const char* str) const { return !(*this str); } bool string::operator(const char* str) const { return !(*this str); }实现 char* string 只能在类外定义bool operator(const char* s,const string str); bool operator (const char* s, const string str); bool operator (const char* s, const string str); bool operator!(const char* s, const string str); bool operator(const char* s, const string str); bool operator(const char* s, const string str);因为我们以及实现了相关的 string char* 相关的运算符重载位置颠倒进一步利用即可bool operator(const char* s, const string str) { return str s; } bool operator (const char* s, const string str) { // s str str s return str s; } bool operator (const char* s, const string str) { // s str str s return str s; } bool operator!(const char* s, const string str) { return str ! s; } bool operator(const char* s, const string str) { // s str str s return str s; } bool operator(const char* s, const string str) { // s str str s; return str s; }所以比较运算符重载看似18个很多但也起始只需要实现4个但还有还有2个是复制前面2个进行复制的所以实际上是需要实现2个多一点点的代码即可。源代码8_22 string · 浪子·悠仁/C 知识库 - 码云 - 开源中国感谢观看悠仁さん