cppPrimer学习14th

cppPrimer学习14th#

从章节14.8开始看#

14.1#

Copy
在什么情况下重载的运算符与内置运算符有所区别?在什么情况下重载的运算符又与内置运算符一样? 不同点: 重载运算符 至少有一个参数为类 重载运算符的求值顺序不一定相同,比如 && || 会依次求值 相同点: 优先级和结核性相同

14.2#

Copy
// 为Sales_data 重载输入,输出,加法和复合赋值 // 为Sales_data 重载输入,输出,加法和复合赋值 #include <iostream> #include <string> //using namespace std; using std::cin; using std::cout; using std::endl; using std::istream; using std::ostream; using std::string; class Sales_data { friend ostream &operator<<(ostream &o, const Sales_data &d); friend istream &operator>>(istream &o, Sales_data &d); friend Sales_data operator+(Sales_data &a, Sales_data &b); public: Sales_data(const string &bookNo, unsigned units, double revenue) : bookNo(bookNo), units_sold(units), revenue(revenue) { } Sales_data() : bookNo("default id"), units_sold(0), revenue(0) {} Sales_data &operator+=(const Sales_data &b) { units_sold += b.units_sold; revenue += b.revenue; } private: std::string bookNo; // name unsigned units_sold = 0; //售卖的数量 double revenue = 0.0; //售卖的总价 double GetAvg() const { return units_sold ? revenue / units_sold : 0; } }; ostream &operator<<(ostream &o, const Sales_data &d) { o << d.bookNo << ": " << d.units_sold << "," << d.revenue << "," << d.GetAvg() << endl; } istream &operator>>(istream &o, Sales_data &d) { cout << "pls input bookNo ,units_sold, revenue" << endl; o >> d.bookNo >> d.units_sold >> d.revenue; if (!o) d = Sales_data(); } Sales_data operator+(Sales_data &a, Sales_data &b) { return Sales_data(a.bookNo, a.units_sold + b.units_sold, a.revenue + b.revenue); } int main(int argc, char const *argv[]) { Sales_data book1("ID1001", 10, 38); cout << book1 << endl; Sales_data book2("ID1002", 10, 40); cout << book2 << endl; Sales_data book3 = book1 + book2; cout << book3 << endl; book3 += book2; cout << book3 << endl; cin >> book1; cout << book1 << endl; while (1) ; return 0; }

14.3#

Copy
string和vector都定义了重载的==以比较各自的对象, 假设svec1和svec2是存放string的vector,确定在下面的表达式中分别使用了哪个版本的==? (a) "cobble" == "stone"     这里比较的是 char* (b) svec1[0] ==svec2[0] string (c) svec1 ==svec2      vector (d) svec[0] == "stone" string

14.4#

Copy
如何确定下列运算符是否应该是类的成员? (a) % 非 (b) %= 是 (c) ++ 是 (d) -> 是 (e) << 非 (f) && 非 (g) == 是 (h) () 是

14.5#

Copy
/* 14.5 在7.5.1节的练习7.40中,编写了下列类中的某一个框架,请问在这个类中应该定义重载的运算符吗?如果是,请写出来。 (a)Book (b)Date (c)Employee (d)Vehicle (e)Object (f)Tree */ #include <iostream> #include <iomanip> class Date { private: int year = 2000; int month = 1; int day = 1; int hour = 0; int min = 0; int sec = 0; public: Date(int y, int m, int d, int h, int mi, int s) : year(y), month(m), day(d), hour(h), min(mi), sec(s) {} friend std::ostream &operator<<(std::ostream &o, Date &d); }; std::ostream &operator<<(std::ostream &o, Date &d) { return o << d.year << "-" << d.month << "-" << d.day << " " << d.hour << ":" << d.min << ":" << d.sec; } int main(int argc, const char **argv) { Date d(2020, 4, 9, 14, 17, 5); std::cout << d << std::endl; while (1) ; return 0; }

14.6#

Copy
参考14.2

14.7#

Copy
class String { public: String(); String(const char *str); friend ostream& operator<<(ostream &os, const String &str); private: char *str; }; ostream& operator<<(ostream &os, const String &str) { cout << str; return os; }

14.8#

Copy
参考14.5

14.9#

Copy
参考14.2

14.10#

Copy
a 正常构造 b 默认构造

14.11#

Copy
price 可能未定义

14.12#

Copy
/* 14.12 你在7.5.1节的练习中曾经选择并编写了一个类,为它定义一个输入运算符并确保该运算符可以处理输入错误。 14.5 在7.5.1节的练习7.40中,编写了下列类中的某一个框架,请问在这个类中应该定义重载的运算符吗?如果是,请写出来。 (a)Book (b)Date (c)Employee (d)Vehicle (e)Object (f)Tree */ #include <iostream> #include <iomanip> class Date { private: int year = 2000; int month = 1; int day = 1; int hour = 0; int min = 0; int sec = 0; public: Date() = default; Date(int y, int m, int d, int h, int mi, int s) : year(y), month(m), day(d), hour(h), min(mi), sec(s) {} friend std::ostream &operator<<(std::ostream &o, Date &d); friend std::istream &operator>>(std::istream &i, Date &d); }; std::ostream &operator<<(std::ostream &o, Date &d) { return o << d.year << "-" << d.month << "-" << d.day << " " << d.hour << ":" << d.min << ":" << d.sec; } std::istream &operator>>(std::istream &o, Date &ret) { Date d; if (o >> d.year >> d.month >> d.day >> d.hour >> d.min >> d.sec) { ret = d; } else { ret = Date(); o.clear(); o.sync(); } } int main(int argc, const char **argv) { Date d(2020, 4, 9, 14, 17, 5); std::cout << d << std::endl; while (1) { std::cout << "pls input date" << std::endl; std::cin >> d; std::cout << d << std::endl; } while (1) ; return 0; }

14.13#

Copy
减法 Sales_data operator-(Sales_data &a, Sales_data &b) { return Sales_data(a.bookNo, a.units_sold - b.units_sold, a.revenue - b.revenue); } Sales_data &operator-=(const Sales_data &b) { units_sold -= b.units_sold; revenue -= b.revenue; }

14.14#

Copy
你觉得为什么调用operator+=来定义operator+比其他方法要更有效? 性能上没有优势,而可读性上后者显然更好。

14.17#

Copy
/* 14.17 重载== 和 != 14.12 你在7.5.1节的练习中曾经选择并编写了一个类,为它定义一个输入运算符并确保该运算符可以处理输入错误。 14.5 在7.5.1节的练习7.40中,编写了下列类中的某一个框架,请问在这个类中应该定义重载的运算符吗?如果是,请写出来。 (a)Book (b)Date (c)Employee (d)Vehicle (e)Object (f)Tree */ #include <iostream> #include <iomanip> class Date { private: int year = 2000; int month = 1; int day = 1; int hour = 0; int min = 0; int sec = 0; public: friend std::ostream &operator<<(std::ostream &o, Date &d); friend std::istream &operator>>(std::istream &i, Date &d); friend bool operator!=(const Date &t, const Date &d); friend bool operator==(const Date &t, const Date &d); Date() = default; Date(int y, int m, int d, int h, int mi, int s) : year(y), month(m), day(d), hour(h), min(mi), sec(s) {} }; std::ostream &operator<<(std::ostream &o, Date &d) { return o << d.year << "-" << d.month << "-" << d.day << " " << d.hour << ":" << d.min << ":" << d.sec; } std::istream &operator>>(std::istream &o, Date &ret) { Date d; if (o >> d.year >> d.month >> d.day >> d.hour >> d.min >> d.sec) { ret = d; } else { ret = Date(); o.clear(); o.sync(); } } bool operator==(const Date &t, const Date &d) { return t.year == d.year && t.month == d.month && t.day == d.day && t.hour == d.hour && t.min == d.min && t.sec == d.sec; } bool operator!=(const Date &t, const Date &d) { return !(t == d); } int main(int argc, const char **argv) { Date a(2020, 4, 9, 14, 17, 5); std::cout << a << std::endl; Date b(2020, 1, 9, 14, 17, 5); std::cout << b << std::endl; std::cout << std::boolalpha << (a == b) << std::endl; std::cout << std::boolalpha << (a != b) << std::endl; // while (1) // { // std::cout << "pls input date" << std::endl; // std::cin >> d; // std::cout << d << std::endl; // } while (1) ; return 0; }

14.19#

Copy
/* 14.19 你在7.5.1节的练习7.40中曾经选择并编写了一个类,你认为它应该含有关系运算符吗?如果是,请实现它;如果不是,解释原因 14.17 重载== 和 != 14.12 你在7.5.1节的练习中曾经选择并编写了一个类,为它定义一个输入运算符并确保该运算符可以处理输入错误。 14.5 在7.5.1节的练习7.40中,编写了下列类中的某一个框架,请问在这个类中应该定义重载的运算符吗?如果是,请写出来。 (a)Book (b)Date (c)Employee (d)Vehicle (e)Object (f)Tree */ #include <iostream> #include <iomanip> class Date { private: int year = 2000; int month = 1; int day = 1; int hour = 0; int min = 0; int sec = 0; public: friend std::ostream &operator<<(std::ostream &o, Date &d); friend std::istream &operator>>(std::istream &i, Date &d); friend bool operator!=(const Date &t, const Date &d); friend bool operator==(const Date &t, const Date &d); friend bool operator>(const Date &t, const Date &d); friend bool operator>=(const Date &t, const Date &d); friend bool operator<(const Date &t, const Date &d); friend bool operator<=(const Date &t, const Date &d); Date() = default; Date(int y, int m, int d, int h, int mi, int s) : year(y), month(m), day(d), hour(h), min(mi), sec(s) {} }; std::ostream &operator<<(std::ostream &o, Date &d) { return o << d.year << "-" << d.month << "-" << d.day << " " << d.hour << ":" << d.min << ":" << d.sec; } std::istream &operator>>(std::istream &o, Date &ret) { Date d; if (o >> d.year >> d.month >> d.day >> d.hour >> d.min >> d.sec) { ret = d; } else { ret = Date(); o.clear(); o.sync(); } } bool operator==(const Date &t, const Date &d) { return t.year == d.year && t.month == d.month && t.day == d.day && t.hour == d.hour && t.min == d.min && t.sec == d.sec; } bool operator!=(const Date &t, const Date &d) { return !(t == d); } bool operator>(const Date &t, const Date &d) { return ((t.year > d.year) || (t.year == d.year && t.month > d.month) || (t.year == d.year && t.month == d.month && t.day > d.day) || (t.year == d.year && t.month == d.month && t.day == d.day && t.hour > d.hour) || (t.year == d.year && t.month == d.month && t.day == d.day && t.hour == d.hour && t.min > d.min) || (t.year == d.year && t.month == d.month && t.day == d.day && t.hour == d.hour && t.min == d.min && t.min > d.min)); } bool operator>=(const Date &t, const Date &d) { return t > d || t == d; } bool operator<(const Date &t, const Date &d) { return !(t >= d); } bool operator<=(const Date &t, const Date &d) { return !(t > d); } int main(int argc, const char **argv) { Date a(2020, 4, 9, 14, 17, 1); Date b(2020, 4, 9, 14, 17, 2); std::cout << std::boolalpha << (a > b) << std::endl; std::cout << std::boolalpha << (a >= b) << std::endl; std::cout << std::boolalpha << (a < b) << std::endl; std::cout << std::boolalpha << (a <= b) << std::endl; std::cout << std::boolalpha << (a >= a) << std::endl; std::cout << std::boolalpha << (a < a) << std::endl; // while (1) // { // std::cout << "pls input date" << std::endl; // std::cin >> d; // std::cout << d << std::endl; // } while (1) ; return 0; }

14.20#

14.21#

Copy
+= 执行加法,+调用+= 的优势在于好看一点 // + 调用 += // Sales_data operator+(Sales_data &a, Sales_data &b) // { // //return Sales_data(a.bookNo, a.units_sold + b.units_sold, a.revenue + b.revenue); // Sales_data t = a; // t += b; // return t; // } // Sales_data &Sales_data::operator+=(const Sales_data &b) // { // units_sold += b.units_sold; // revenue += b.revenue; // return *this; // } // += 调用+ Sales_data operator+(const Sales_data &a, const Sales_data &b) { Sales_data t = a; t.units_sold += b.units_sold; t.revenue += b.revenue; return t; } Sales_data &Sales_data::operator+=(const Sales_data &b) { *this = *this + b; return *this; }

14.22#

Copy
/* 14.22:定义赋值运算符的一个新版本,使得我们能把一个表示ISBN的string赋给一个Sales_data对象 */ Sales_data &operator=(const std::string &s) { bookNo = s; return *this; }

14.23#

Copy
//14.23:为你的StrVec类定义一个initializer_list赋值运算符 StrVec &StrVec::operator=(initializer_list<string> li) { auto data = allc_n_copy(li.begin(), li.end()); free(); elements = data.first; first_free = cap = data.second; return *this; }

14.24#

Copy
// 14.24:你在7.5.1节的7.40中曾经选择并编写了一个类,你认为它应该含有拷贝赋值和移动赋值运算符吗? // 如果是,请实现它们 date 不需要,没有指针相关的

14.25#

Copy
//14.25上题的这个类还需要定义其他赋值运算符吗?如果是,请实现它们;同时说明运算对象应该是什么类型并解释原因 // string > date Date &Date::operator=(const std::string &s) { std::istringstream in(s); in >> *this; return *this; }

14.29#

Copy
为什么不定义const版本的递增和递减运算符 因为会改变对象的值

14.33#

Copy
一个重载的函数调用运算符应该接受几个运算对象 0个或者多个,和普通函数一样,上限这个不去细究

14.34#

Copy
//定义一个函数对象类,令其执行if-then-else的操作:该类的调用运算符接受三个形参, //它首先检查第一个形参,如果成功返回第二个形参的值,如果不成功返回第三个形参的值 struct ifelsethen { int operator(bool flag,int a,int b) { return flag? a:b; } }

14.35#

14.36#

Copy
/* 14.36 保存到vector 14.35 编写一个类似PrintString的类,令其从istream中读取一行输入,然后返回一个表示我们所读内容的string。如果读取失败,返回空string */ #include <iostream> #include <string> #include <vector> class PrintStringLine { public: std::string operator()(std::istream &in) { std::string line; if (getline(in, line)) return line; else return std::string(); } }; int main(int argc, char const *argv[]) { PrintStringLine p; //std::cout << "--" << p(std::cin) << "--" std::endl; std::vector<std::string> v; // v.push_back(p(std::cin)); // v.push_back(p(std::cin)); // v.push_back(p(std::cin)); // v.push_back(p(std::cin)); // v.push_back(p(std::cin)); for (std::string tmp; !(tmp = PrintStringLine()(std::cin)).empty();) v.push_back(tmp); for (auto ch : v) std::cout << "~" << ch << "~" << std::endl; while (1) ; return 0; }

14.37#

Copy
/* 14.37 编写一个类令其检查两个值是否相等。使用该对象及标准库算法编写程序,令其替换某个序列中具有给定值的所有实例 */ #include <vector> #include <algorithm> #include <iostream> class Equal { private: int data; public: Equal(int c) : data(c) {} bool operator()(int a) { return a == data; } }; int main(int argc, char const *argv[]) { std::vector<int> v = {1, 2, 3, 4, 5, 6, 2, 3, 2, 1, 4, 6, 7, 8, 1, 2, 3, 1}; std::replace_if(v.begin(), v.end(), Equal(1), 9999); // for (auto ch : v) // std::cout << ch << ","; // std::cout << std::endl; std::for_each(v.begin(), v.end(), [](std::vector<int>::value_type c) { std::cout << c << ","; }); //std::for_each(v.begin(), v.end(), [](int c) { std::cout << c << ","; }); while (1) { /* code */ } return 0; }

14.38#

14.39#

Copy
/* 14.39 修改其报告1~9的单词有几个,10以上的有几个 14.38 编写一个类令其检查某个给定的string对象的长度是否与一个阀值相等。使用该对象编写程序,统计并报告在输入的文件中长度为1的单词有多少个、长度为2的单词有多少个。 */ #include <string> #include <fstream> #include <iostream> #include <vector> class StrLen { private: int len; bool cmp; public: StrLen(int l, bool cmp = false) : len(l), cmp(cmp) {} bool operator()(const std::string &s) { if (cmp == false) return s.size() == len; else return s.size() >= len; } }; int main(int argc, char const *argv[]) { std::string path = "D:\\1.txt"; std::ifstream infile(path); if (!infile) { std::cout << "err to open path" << path << std::endl; while (1) ; } std::string s; std::vector<std::string> v; int len_1 = 0, len_2 = 0, len_10_big = 0, len_10_lit = 0; StrLen l2(2); StrLen l1(1); StrLen l10(10, true); while (infile >> s) { //v.push_back(std::move(s)); if (l1(s)) len_1++; if (l2(s)) len_2++; if (l10(s)) len_10_big++; else len_10_lit++; } std::cout << "len=1,count=" << len_1 << std::endl; std::cout << "len=2,count=" << len_2 << std::endl; std::cout << "len>=10,count=" << len_10_big << std::endl; std::cout << "len<10>,count=" << len_10_lit << std::endl; while (1) ; return 0; }

14.40#

Copy
/* 14.40 重写10.3.2的P349 的biggies 函数,使用可调用类替换lambda */ #include <string> #include <vector> #include <iostream> #include <algorithm> using std::cin; using std::cout; using std::endl; using std::find_if; using std::for_each; using std::sort; using std::stable_sort; using std::string; using std::vector; class WordsABSizeCmp { public: bool operator()(const string &a, const string &b) { return a.size() < b.size(); } }; class WordsBigThan { private: int default_size; public: WordsBigThan(int dsize) : default_size(dsize) {} bool operator()(const string &a) { return a.size() >= default_size; } }; void elimdups(vector<string> &words) { sort(words.begin(), words.end()); auto end_unique = unique(words.begin(), words.end()); words.erase(end_unique, words.end()); } string make_plural(size_t ctr, string const &word, string const &ending) { return (ctr > 1) ? word + ending : word; } class PrintString { private: std::ostream &o; public: PrintString(std::ostream &o = std::cout) : o(o) {} std::ostream &operator()(const string &s) { return o << s << ","; } }; void biggies(vector<string> &words, vector<string>::size_type sz) { // 删除重复单词 elimdups(words); // 按照长度排序单词 stable_sort(words.begin(), words.end(), WordsABSizeCmp()); // 找到第一个size大于某值的元素 auto wc = find_if(words.begin(), words.end(), WordsBigThan(sz)); // 计算size大于某值的数目 auto count = words.end() - wc; cout << count << make_plural(count, "word", "s") << " of length " << sz << "or longer" << endl; for_each(wc, words.end(), PrintString()); } int main() { vector<string> vec{"fox", "jumps", "over", "quick", "red", "red", "slow", "the", "turtle"}; biggies(vec, 4); while (1) { /* code */ } }

14.41#

Copy
你认为C++11新标准为什么要增加lambda?对于你自己来说,什么情况下会使用lambda,什么情况下会使用类? lambda 适合短小功能,不会反复复用 类,反复复用,功能多

14.42#

Copy
(a)统计大于1024的值有多少个。 std::count_if(i.cbegin(),i.cend(),std::bind(std::greater<int>(),_1,1024)); (b)找到第一个不等于pooh的字符串。 std::find_if(i.cbegin(),i.cend(),std::bind(std::not_equal_to<string>(),_1,"pooh")); (c)将所有的值乘以2. std::transform(i.begin(),i.end(),i.begin(),bind(std::multiplies<int>(),_1,2));

14.43#

Copy
/* 14.43:使用标准库函数对象判断一个给定的int值是否能被int容器中的所有元素整除 */ #include <algorithm> #include <iostream> #include <vector> #include <functional> using namespace std::placeholders; bool IfDivVec(int a, std::vector<int> &v) { auto w = std::find_if(v.cbegin(), v.cend(), std::bind(std::modulus<int>(), _1, a)); return w == v.cend(); } int main(int argc, char const *argv[]) { int a = 3; std::vector<int> v = {3, 6, 9, 18, 24}; std::cout << std::boolalpha << IfDivVec(a, v) << std::endl; v.push_back(13); std::cout << std::boolalpha << IfDivVec(a, v) << std::endl; while (1) ; return 0; } // auto data = {2, 3, 4, 5}; // int input; // std::cin >> input; // std::modulus<int> mod; // auto predicator = [&](int i) { return 0 == mod(input, i); }; // auto is_divisible = std::any_of(data.begin(), data.end(), predicator); // std::cout << (is_divisible ? "Yes!" : "No!") << std::endl;

14.45#

Copy
14.45 编写类型转换运算符转换 Sales_data 到 string 和double operator const string() { return bookNo; } operator const double() { return GetAvg(); } int main(int argc, char const *argv[]) { Sales_data book1("ID1001", 10, 38); cout << book1 << endl; cout << static_cast<string>(book1) << endl; cout << static_cast<double>(book1) << endl; while (1) ; return 0; }

14.46#

Copy
14.46 你认为应该定义上述两种类型转换吗 ? 是否要定义成 explicit? 不应该,转换的含义不明确,应该作为具体的成员函数 如果定义了,应该定义成 explicit 否则cout<<xxx 这类操作不知道怎么操作而且含义不精确

14.47#

Copy
struct Integral { operator const int(); 返回值不能改变 operator int() const; 不会改变类对象的内容 };

14.48#

14.49#

TODO#

14.50#

Copy
// 可能用到哪些类类型的转换序列呢?说明初始化是否正确并解释原因 struct LongDouble { LongDouble(double = 0.0); operator double(); operator float(); }; LongDouble ldObj; int ex1 = ldObj; // float 或者 double 二义性 float ex2 ldObj; // 调用operator float();

14.51#

Copy
在调用calc的过程中,可能用到哪些类型转换序列呢?说明最佳可行函数是如何选拔出来的。 void calc(int); void calc(LongDouble); double dval; calc(dval); //调用calc(int) 因为doube转int是标准类型转换

14.52#

Copy
14.52 在下面的加法表达式中分别选用了哪个operator? 列出候选函数、可行函数及为每个可行函数的实参执行的类型转换 struct longDouble { //用于演示的成员operator+; 在通常情况下+s是个非成员 longDouble operator+(const SmallInt&); //其他成员与14.9.2节一致 }; longDouble operator+(longDouble&, double); SmallInt si; longDouble ld; ld = si + ld; //没有转换的 ld = ld + si; // 二义性 // 非成员 operator+ , >>> int转double // 成员 operator+(const SmallInt&) 完全匹配的

14.53#

Copy
14.53:假设我们已经定义了如第522页所示的SmallInt,判断下面的加法表达式是否合法。 如果合法,使用了哪个加法运算符?如果不合法,应该怎样修改代码才能使其合法? SamllInt sl; double d = s1 + 3.14; // 1. 非成员函数 double转SamllInt 也就是构造函数 SamllInt(int) ===> double>int // 2. SamllInt 转double 赋值 // 1. s1转int, // 2. int 提升到 double SmallInt s1; double d = s1 + SmallInt(3.14);

StrBlob StrBlobPtr Strvec String#

strblob.h

Copy
#ifndef __STR_BLOB_H__ #define __STR_BLOB_H__ #include <vector> #include <memory> #include <iostream> #include <initializer_list> #include <exception> using std::cout; using std::endl; using std::initializer_list; using std::make_shared; using std::ostream; using std::shared_ptr; using std::string; using std::vector; class StrBlobPtr; class ConstStrBlobPtr; /** * @brief vector<string> * */ class StrBlob { using size_type = vector<string>::size_type; friend std::ostream &operator<<(std::ostream &o, const StrBlob &s); friend bool operator==(const StrBlob &, const StrBlob &); friend bool operator!=(const StrBlob &, const StrBlob &); friend bool operator<(const StrBlob &, const StrBlob &); friend bool operator>(const StrBlob &, const StrBlob &); friend bool operator<=(const StrBlob &, const StrBlob &); friend bool operator>=(const StrBlob &, const StrBlob &); friend class StrBlobPtr; friend class ConstStrBlobPtr; private: shared_ptr<vector<string>> data; void check(size_type at, const string err_message) const; public: StrBlob() : data(make_shared<vector<string>>()) {} StrBlob(initializer_list<string> il) : data(make_shared<vector<string>>(il)) {} // 拷贝构造,拷贝赋值,移动构造,移动赋值 StrBlob(const StrBlob &s) : data(make_shared<vector<string>>(*s.data)) {} StrBlob &operator=(const StrBlob &s); StrBlob(StrBlob &&s) noexcept : data(std::move(s.data)) {} StrBlob &operator=(StrBlob &&s); void push_back(const string &s) { data->push_back(s); } void push_back(string &&s) { data->push_back(std::move(s)); } void pop_back(); string &front(); string &back(); const string &front() const; const string &back() const; string &operator[](size_t at); const string &operator[](size_t at) const; // 迭代器相关的 StrBlobPtr begin(); // { return StrBlobPtr(*this); } StrBlobPtr end(); //{ return StrBlobPtr(*this, data->size()); } ConstStrBlobPtr cbegin(); // { return StrBlobPtr(*this); } ConstStrBlobPtr cend(); //{ return StrBlobPtr(*this, data->size()); } size_type size() const { return data->size(); } }; inline StrBlob &StrBlob::operator=(const StrBlob &s) { data = make_shared<vector<string>>(*s.data); return *this; } inline StrBlob &StrBlob::operator=(StrBlob &&s) { if (this != &s) { data = s.data; s.data = nullptr; } return *this; } inline void StrBlob::check(size_type at, const string err_message) const { if (at >= data->size()) throw std::out_of_range(err_message); } inline void StrBlob::pop_back() { check(0, "try to pop empty vector!!!"); data->pop_back(); } inline string &StrBlob::front() { check(0, "try to get front empty vector!!!"); return data->front(); } inline string &StrBlob::back() { check(0, "try to get back empty vector!!!"); return data->back(); } inline const string &StrBlob::front() const { check(0, "try to get front empty vector!!!"); return data->front(); } inline const string &StrBlob::back() const { check(0, "try to get back empty vector!!!"); return data->back(); } inline string &StrBlob::operator[](size_t at) { check(at, "out of range!!!"); return data->at(at); } inline const string &StrBlob::operator[](size_t at) const { check(at, "out of range!!!"); return data->at(at); } /** * @brief vector<string> iterator * */ class StrBlobPtr { friend bool operator==(const StrBlobPtr &, const StrBlobPtr &); friend bool operator!=(const StrBlobPtr &, const StrBlobPtr &); friend bool operator<(const StrBlobPtr &, const StrBlobPtr &); friend bool operator>(const StrBlobPtr &, const StrBlobPtr &); friend bool operator<=(const StrBlobPtr &, const StrBlobPtr &); friend bool operator>=(const StrBlobPtr &, const StrBlobPtr &); private: std::weak_ptr<vector<string>> wptr; // convert weak_ptr to shared_ptr shared_ptr<vector<string>> check(size_t at, string err_msg) const; size_t curr; public: StrBlobPtr() : curr(0) {} StrBlobPtr(StrBlob &s, size_t at = 0) : wptr(s.data), curr(at) {} StrBlobPtr &operator++(); StrBlobPtr &operator--(); // 后置版本返回的是原来的值的拷贝,再++,所以不能返回引用 StrBlobPtr operator++(int); StrBlobPtr operator--(int); StrBlobPtr &operator+=(int); StrBlobPtr &operator-=(int); StrBlobPtr operator+(int) const; StrBlobPtr operator-(int) const; string &operator[](size_t); const string &operator[](size_t) const; string &operator*(); const string &operator*() const; }; inline shared_ptr<vector<string>> StrBlobPtr::check(size_t at, string err_msg) const { auto ret = wptr.lock(); if (!ret) throw std::runtime_error("No shared_ptr get!!!"); if (at > ret->size()) //because of at==ret->size when iterator arrive the end throw std::out_of_range("out of range to check StrBlobPtr of" + err_msg); return ret; } inline StrBlobPtr &StrBlobPtr::operator++() { ++curr; check(curr, "err to ++ "); return *this; } inline StrBlobPtr &StrBlobPtr::operator--() { --curr; check(curr, "err to -- "); return *this; } inline StrBlobPtr StrBlobPtr::operator++(int) { StrBlobPtr ret = *this; ++*this; return ret; } inline StrBlobPtr StrBlobPtr::operator--(int) { StrBlobPtr ret = *this; --*this; return ret; } inline StrBlobPtr &StrBlobPtr::operator+=(int offset) { curr += offset; check(curr, "err to += "); return *this; } inline StrBlobPtr &StrBlobPtr::operator-=(int offset) { curr -= offset; check(curr, "err to -= "); return *this; } inline StrBlobPtr StrBlobPtr::operator+(int offset) const { StrBlobPtr ret = *this; ret += offset; return *this; } inline StrBlobPtr StrBlobPtr::operator-(int offset) const { StrBlobPtr ret = *this; ret -= offset; return *this; } inline string &StrBlobPtr::operator[](size_t offset) { auto ret = check(offset, "Get [] err"); return (*ret)[offset]; } inline const string &StrBlobPtr::operator[](size_t offset) const { auto ret = check(offset, "Get [] err"); return (*ret)[offset]; } inline string &StrBlobPtr::operator*() { //auto ret = check(curr, "Get [] err"); //return ret->at(curr); return (*this)[curr]; } inline const string &StrBlobPtr::operator*() const { return (*this)[curr]; } // 个人觉得应该是 非const的迭代器继承自const的迭代器 const_iterator // --这里的const 是指不能通过该迭代器修改指向的内容 /** * @brief vector<string> iterator * */ class ConstStrBlobPtr { friend bool operator==(const ConstStrBlobPtr &, const ConstStrBlobPtr &); friend bool operator!=(const ConstStrBlobPtr &, const ConstStrBlobPtr &); friend bool operator<(const ConstStrBlobPtr &, const ConstStrBlobPtr &); friend bool operator>(const ConstStrBlobPtr &, const ConstStrBlobPtr &); friend bool operator<=(const ConstStrBlobPtr &, const ConstStrBlobPtr &); friend bool operator>=(const ConstStrBlobPtr &, const ConstStrBlobPtr &); private: std::weak_ptr<vector<string>> wptr; // convert weak_ptr to shared_ptr shared_ptr<vector<string>> check(size_t at, string err_msg) const; size_t curr; public: ConstStrBlobPtr() : curr(0) {} ConstStrBlobPtr(const StrBlob &s, size_t at = 0) : wptr(s.data), curr(at) {} ConstStrBlobPtr &operator++(); ConstStrBlobPtr &operator--(); // 后置版本返回的是原来的值的拷贝,再++,所以不能返回引用 ConstStrBlobPtr operator++(int); ConstStrBlobPtr operator--(int); ConstStrBlobPtr &operator+=(int); ConstStrBlobPtr &operator-=(int); ConstStrBlobPtr operator+(int) const; ConstStrBlobPtr operator-(int) const; //string &operator[](size_t); --这里的const 是指不能通过该迭代器修改指向的内容 const string &operator[](size_t) const; //string &operator*(); const string &operator*() const; }; inline shared_ptr<vector<string>> ConstStrBlobPtr::check(size_t at, string err_msg) const { auto ret = wptr.lock(); if (!ret) throw std::runtime_error("No shared_ptr get!!!"); if (at > ret->size()) //because of at==ret->size when iterator arrive the end throw std::out_of_range("out of range to check ConstStrBlobPtr of" + err_msg); return ret; } inline ConstStrBlobPtr &ConstStrBlobPtr::operator++() { ++curr; check(curr, "err to ++ "); return *this; } inline ConstStrBlobPtr &ConstStrBlobPtr::operator--() { --curr; check(curr, "err to -- "); return *this; } inline ConstStrBlobPtr ConstStrBlobPtr::operator++(int) { ConstStrBlobPtr ret = *this; ++*this; return ret; } inline ConstStrBlobPtr ConstStrBlobPtr::operator--(int) { ConstStrBlobPtr ret = *this; --*this; return ret; } inline ConstStrBlobPtr &ConstStrBlobPtr::operator+=(int offset) { curr += offset; check(curr, "err to += "); return *this; } inline ConstStrBlobPtr &ConstStrBlobPtr::operator-=(int offset) { curr -= offset; check(curr, "err to -= "); return *this; } inline ConstStrBlobPtr ConstStrBlobPtr::operator+(int offset) const { ConstStrBlobPtr ret = *this; ret += offset; return *this; } inline ConstStrBlobPtr ConstStrBlobPtr::operator-(int offset) const { ConstStrBlobPtr ret = *this; ret -= offset; return *this; } // inline string &ConstStrBlobPtr::operator[](size_t offset) // { // auto ret = check(offset, "Get [] err"); // return (*ret)[offset]; // } inline const string &ConstStrBlobPtr::operator[](size_t offset) const { auto ret = check(offset, "Get [] err"); return (*ret)[offset]; } // inline string &ConstStrBlobPtr::operator*() // { // //auto ret = check(curr, "Get [] err"); // //return ret->at(curr); // return (*this)[curr]; // } inline const string &ConstStrBlobPtr::operator*() const { return (*this)[curr]; } #endif // !__STR_BLOB_H__

strblob.cpp

Copy
#include "StrBlob.h" //**************************************************************************** std::ostream &operator<<(std::ostream &o, const StrBlob &s) { for (size_t i = 0; i != s.size(); i++) o << s[i] << ","; return o; } bool operator==(const StrBlob &a, const StrBlob &b) { return *a.data == *b.data; } bool operator!=(const StrBlob &a, const StrBlob &b) { return !(a == b); } bool operator<(const StrBlob &a, const StrBlob &b) { return std::lexicographical_compare(a.data->begin(), a.data->end(), b.data->begin(), b.data->end()); } bool operator>(const StrBlob &a, const StrBlob &b) { return b < a; } bool operator<=(const StrBlob &a, const StrBlob &b) { return !(a > b); } bool operator>=(const StrBlob &a, const StrBlob &b) { return !(a < b); } StrBlobPtr StrBlob::begin() { return StrBlobPtr(*this); } StrBlobPtr StrBlob::end() { return StrBlobPtr(*this, data->size()); } ConstStrBlobPtr StrBlob::cbegin() { return ConstStrBlobPtr(*this); } ConstStrBlobPtr StrBlob::cend() { return ConstStrBlobPtr(*this, data->size()); } //**************************************************************************** bool operator==(const StrBlobPtr &a, const StrBlobPtr &b) { return a.curr == b.curr; } bool operator!=(const StrBlobPtr &a, const StrBlobPtr &b) { return !(a == b); } bool operator<(const StrBlobPtr &a, const StrBlobPtr &b) { return (a.curr < b.curr); } bool operator>(const StrBlobPtr &a, const StrBlobPtr &b) { return (b < a); } bool operator<=(const StrBlobPtr &a, const StrBlobPtr &b) { return (b > a); } bool operator>=(const StrBlobPtr &a, const StrBlobPtr &b) { return (a < b); } //**************************************************************************** bool operator==(const ConstStrBlobPtr &a, const ConstStrBlobPtr &b) { return a.curr == b.curr; } bool operator!=(const ConstStrBlobPtr &a, const ConstStrBlobPtr &b) { return !(a == b); } bool operator<(const ConstStrBlobPtr &a, const ConstStrBlobPtr &b) { return (a.curr < b.curr); } bool operator>(const ConstStrBlobPtr &a, const ConstStrBlobPtr &b) { return (b < a); } bool operator<=(const ConstStrBlobPtr &a, const ConstStrBlobPtr &b) { return (b > a); } bool operator>=(const ConstStrBlobPtr &a, const ConstStrBlobPtr &b) { return (a < b); } //**************************************************************************** int main(int argc, char const *argv[]) { try { StrBlob ls({"A", "B", "C"}); ls.push_back("D"); ls.pop_back(); std::cout << ls.front() << std::endl; std::cout << ls.back() << std::endl; std::cout << ls << std::endl; StrBlob ls2({"A", "B", "C"}); std::cout << std::boolalpha << (ls == ls2) << std::endl; ls2.push_back("D"); std::cout << std::boolalpha << (ls <= ls2) << std::endl; // ls.push_back("E"); std::cout << ls << std::endl; std::cout << ls2 << std::endl; std::cout << std::boolalpha << (ls2 > ls) << std::endl; std::cout << "-------------------------------------" << std::endl; std::cout << "-------------Test iterator-----------" << std::endl; std::cout << "-------------------------------------" << std::endl; for (auto i = ls.begin(); i != ls.end(); i++) { std::cout << *i << ","; *i = "(" + *i + ")"; } for (auto i = ls.begin(); i != ls.end(); i++) std::cout << *i << ","; for (auto i = ls.cbegin(); i != ls.cend(); i++) { std::cout << *i << ","; //*i = "(" + *i + ")"; // does not match any in class // inline string &ConstStrBlobPtr::operator[](size_t offset) // 只有 const string } /* code */ } catch (const std::exception &e) { std::cerr << e.what() << '\n'; } while (1) ; return 0; }
posted @   zongzi10010  阅读(148)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?
点击右上角即可分享
微信分享提示
CONTENTS