笔记较为零散,都是自己不熟悉的知识点。
习题答案至于一个.h 和.cc 中,需要演示某一题直接修改 #define NUM****, 如运行14.30题为#define NUM1430;
Alice Emma has long flowing red hair. Her Daddy says when the wind blows through her hair, it looks almost alive, like a fiery bird in flight. A beautiful fiery bird, he tells her, magical but untamed. "Daddy, shush, there is no such thing," she tells him, at the same time wanting him to tell her more. Shyly, she asks, "I mean, Daddy, is there?"
//Chapter14.h #ifndef CHAPTER_10_H #define CHAPTER_10_H #include <iostream> #include <memory> #include <vector> #include <string> #include <initializer_list> #include <algorithm> #include <exception> using namespace std; //14.2 class Sales_data { friend istream& operator>>(istream&, Sales_data&); // input friend ostream& operator<<(ostream&, const Sales_data&); // output friend Sales_data operator+(const Sales_data&, const Sales_data&); // addition public: Sales_data(const string& s, unsigned n, double p) : bookNo(s), units_sold(n), revenue(n * p) { } Sales_data() : Sales_data("", 0, 0.0f) {} Sales_data(const string& s) : Sales_data(s, 0, 0.0f) {} Sales_data(istream& is); Sales_data& operator=(const string&); //14.22 Sales_data& operator+=(const Sales_data&); // compound-assignment string isbn() const { return bookNo; } explicit operator string() const { return bookNo; } //14.45 explicit operator double() const { return avg_price(); } //14.45 private: inline double avg_price() const; string bookNo; unsigned units_sold = 0; double revenue = 0.0; }; istream& operator>>(istream&, Sales_data&); ostream& operator<<(ostream&, const Sales_data&); Sales_data operator+(const Sales_data&, const Sales_data&); inline double Sales_data::avg_price() const{ return units_sold ? revenue / units_sold : 0; } Sales_data::Sales_data(istream& is) : Sales_data(){ is >> *this; } Sales_data& Sales_data::operator+=(const Sales_data& rhs){ units_sold += rhs.units_sold; revenue += rhs.revenue; return *this; } istream& operator>>(istream& is, Sales_data& item){ double price = 0.0; is >> item.bookNo >> item.units_sold >> price; if (is) item.revenue = price * item.units_sold; else item = Sales_data(); return is; } /* istream&operator>>(istream& in, Sales_data& s) //14.11 { double price; in >> s.bookNo>> s.units_sold>> price; s.revenue = s.units_sold * price; return in; } */ ostream& operator<<(ostream& os, const Sales_data& item){ os << item.isbn() << " " << item.units_sold << " " << item.revenue << " " << item.avg_price(); return os; } Sales_data operator+(const Sales_data& lhs, const Sales_data& rhs){ Sales_data sum = lhs; sum += rhs; return sum; } Sales_data& Sales_data::operator=(const string& isbn){ //14.22 *this = Sales_data(isbn); return *this; } //14.5 class Book { friend istream& operator>>(istream&, Book&); // input friend ostream& operator<<(ostream&, const Book&); // output friend bool operator==(const Book&, const Book&); friend bool operator!=(const Book&, const Book&); friend bool operator<(const Book&, const Book&); friend bool operator>(const Book&, const Book&); friend Book operator+(const Book&, const Book&); public: Book() = default; Book(unsigned no, string name, string author, string pubdate):no_(no), name_(name), author_(author), pubdate_(pubdate) { } Book(istream &in) { in >> no_ >> name_ >> author_ >> pubdate_; } Book& operator+=(const Book&); private: unsigned no_; string name_; string author_; string pubdate_; unsigned number_; }; istream& operator>>(istream&, Book&); // input ostream& operator<<(ostream&, const Book&); // output bool operator==(const Book&, const Book&); bool operator!=(const Book&, const Book&); bool operator<(const Book&, const Book&); bool operator>(const Book&, const Book&); Book operator+(const Book&, const Book&); istream& operator>>(istream& in, Book& book){ in >> book.no_ >> book.name_ >> book.author_ >> book.pubdate_ >> book.number_; if (!in) book = Book(); return in; } ostream& operator<<(ostream& out, const Book& book){ out << book.no_ << " " << book.name_ << " " << book.author_ << " " << book.pubdate_ << " " << book.number_ << endl; return out; } bool operator==(const Book& lhs, const Book& rhs){ return lhs.no_ == rhs.no_; } bool operator!=(const Book& lhs, const Book& rhs){ return !(lhs == rhs); } bool operator<(const Book& lhs, const Book& rhs){ return lhs.no_ < rhs.no_; } bool operator>(const Book& lhs, const Book& rhs){ return rhs < lhs; } Book& Book::operator+=(const Book& rhs){ if (rhs == *this) this->number_ += rhs.number_; return *this; } Book operator+(const Book& lhs, const Book& rhs){ Book book = lhs; book += rhs; return book; } //14.7 class String { friend ostream& operator<<(ostream&, const String&); friend istream& operator>>(istream&, String&); friend bool operator==(const String&, const String&); friend bool operator!=(const String&, const String&); friend bool operator<(const String&, const String&); friend bool operator>(const String&, const String&); friend bool operator<=(const String&, const String&); friend bool operator>=(const String&, const String&); public: String() : String("") {} String(const char*); String(const String&); String& operator=(const String&); String(String&&) noexcept; String& operator=(String&&) noexcept; ~String(); void push_back(const char); char* begin() const { return elements; } char* end() const { return last_elem; } char& operator[](size_t n) { return elements[n]; } //14.26 const char& operator[](size_t n) const { return elements[n]; } //14.26 const char* c_str() const { return elements; } size_t size() const { return last_elem - elements; } size_t length() const { return size(); } size_t capacity() const { return cap - elements; } void reserve(size_t); void resize(size_t); void resize(size_t, char); private: pair<char*, char*> alloc_n_copy(const char*, const char*); void range_initializer(const char*, const char*); void free(); void reallocate(); void alloc_n_move(size_t new_cap); void chk_n_alloc() { if (first_free == cap) reallocate(); } private: char* elements; char* last_elem; char* first_free; char* cap; allocator<char> alloc; }; ostream& operator<<(ostream&, const String&); istream& operator>>(istream&, String&); bool operator==(const String&, const String&); bool operator!=(const String&, const String&); bool operator<(const String&, const String&); bool operator>(const String&, const String&); bool operator<=(const String&, const String&); bool operator>=(const String&, const String&); ostream& operator<<(ostream& os, const String& lhs){ os << lhs.c_str(); return os; } istream& operator>>(istream& is, String& rhs){ for (char c; (c = is.get()) != '\n';) { rhs.push_back(c); } return is; } bool operator==(const String& lhs, const String& rhs){ return (lhs.size() == rhs.size() && equal(lhs.begin(), lhs.end(), rhs.begin())); } bool operator!=(const String& lhs, const String& rhs){ return !(lhs == rhs); } bool operator<(const String& lhs, const String& rhs){ return lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end()); } bool operator>(const String& lhs, const String& rhs){ return rhs < lhs; } bool operator<=(const String& lhs, const String& rhs){ return !(rhs < lhs); } bool operator>=(const String& lhs, const String& rhs){ return !(lhs < rhs); } String::String(const char* s){ char* sl = const_cast<char*>(s); while (*sl) ++sl; range_initializer(s, ++sl); } String::String(const String& rhs){ range_initializer(rhs.elements, rhs.first_free); } String& String::operator=(const String& rhs){ auto newstr = alloc_n_copy(rhs.elements, rhs.first_free); free(); elements = newstr.first; first_free = cap = newstr.second; last_elem = first_free - 1; return *this; } String::String(String&& s) noexcept : elements(s.elements), last_elem(s.last_elem), first_free(s.first_free), cap(s.cap){ s.elements = s.last_elem = s.first_free = s.cap = nullptr; } String& String::operator=(String&& rhs) noexcept{ if (this != &rhs) { free(); elements = rhs.elements; last_elem = rhs.last_elem; first_free = rhs.first_free; cap = rhs.cap; rhs.elements = rhs.last_elem = rhs.first_free = rhs.cap = nullptr; } return *this; } String::~String(){ free(); } //=========================================================================== // // members // //=========================================================================== void String::push_back(const char c){ chk_n_alloc(); *last_elem = c; last_elem = first_free; alloc.construct(first_free++, '\0'); } void String::reallocate(){ auto newcapacity = size() ? 2 * (size() + 1) : 2; alloc_n_move(newcapacity); } void String::alloc_n_move(size_t new_cap){ auto newdata = alloc.allocate(new_cap); auto dest = newdata; auto elem = elements; for (size_t i = 0; i != size() + 1; ++i) alloc.construct(dest++, move(*elem++)); free(); elements = newdata; last_elem = dest - 1; first_free = dest; cap = elements + new_cap; } void String::free(){ if (elements) { for_each(elements, first_free, [this](char& c) { alloc.destroy(&c); }); alloc.deallocate(elements, cap - elements); } } pair<char*, char*> String::alloc_n_copy(const char* b, const char* e){ auto str = alloc.allocate(e - b); return {str, uninitialized_copy(b, e, str)}; } void String::range_initializer(const char* first, const char* last){ auto newstr = alloc_n_copy(first, last); elements = newstr.first; first_free = cap = newstr.second; last_elem = first_free - 1; } void String::reserve(size_t new_cap){ if (new_cap <= capacity()) return; alloc_n_move(new_cap); } void String::resize(size_t count, char c){ if (count > size()) { if (count > capacity()) reserve(count * 2); for (size_t i = size(); i != count; ++i) { *last_elem++ = c; alloc.construct(first_free++, '\0'); } } else if (count < size()) { while (last_elem != elements + count) { --last_elem; alloc.destroy(--first_free); } *last_elem = '\0'; } } void String::resize(size_t count){ resize(count, ' '); } //14.16 class StrBlobPtr; class ConstStrBlobPtr; //================================================================================= // // StrBlob - custom vector<string> // //================================================================================= class StrBlob { using size_type = vector<string>::size_type; friend class ConstStrBlobPtr; friend class StrBlobPtr; 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&); public: StrBlob() : data(make_shared<vector<string>>()) {} StrBlob(initializer_list<string> il) : data(make_shared<vector<string>>(il)) { } StrBlob(const StrBlob& sb) : data(make_shared<vector<string>>(*sb.data)) {} StrBlob& operator=(const StrBlob&); StrBlob(StrBlob&& rhs) noexcept : data(move(rhs.data)) {} StrBlob& operator=(StrBlob&&) noexcept; StrBlobPtr begin(); StrBlobPtr end(); ConstStrBlobPtr cbegin() const; ConstStrBlobPtr cend() const; string& operator[](size_t n); const string& operator[](size_t n) const; size_type size() const { return data->size(); } bool empty() const { return data->empty(); } void push_back(const string& t) { data->push_back(t); } void push_back(string&& s) { data->push_back(move(s)); } void pop_back(); string& front(); string& back(); const string& front() const; const string& back() const; private: void check(size_type, const string&) const; shared_ptr<vector<string>> data; }; bool operator==(const StrBlob&, const StrBlob&); bool operator!=(const StrBlob&, const StrBlob&); bool operator<(const StrBlob&, const StrBlob&); bool operator>(const StrBlob&, const StrBlob&); bool operator<=(const StrBlob&, const StrBlob&); bool operator>=(const StrBlob&, const StrBlob&); inline void StrBlob::pop_back(){ check(0, "pop_back on empty StrBlob"); data->pop_back(); } inline string& StrBlob::front(){ check(0, "front on empty StrBlob"); return data->front(); } inline string& StrBlob::back(){ check(0, "back on empty StrBlob"); return data->back(); } inline const string& StrBlob::front() const{ check(0, "front on empty StrBlob"); return data->front(); } inline const string& StrBlob::back() const{ check(0, "back on empty StrBlob"); return data->back(); } inline void StrBlob::check(size_type i, const string& msg) const{ if (i >= data->size()) throw out_of_range(msg); } inline string& StrBlob::operator[](size_t n){ check(n, "out of range"); return data->at(n); } inline const string& StrBlob::operator[](size_t n) const{ check(n, "out_of_range"); return data->at(n); } //================================================================================= // // StrBlobPtr - custom iterator of StrBlob // //================================================================================= 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&); public: StrBlobPtr() : curr(0) {} StrBlobPtr(StrBlob& s, size_t sz = 0) : wptr(s.data), curr(sz) {} const string &operator*() const; //14.30 const string *operator->() const; StrBlobPtr &operator++(); //14.27 StrBlobPtr &operator--(); StrBlobPtr operator++(int); StrBlobPtr operator--(int); StrBlobPtr &operator+=(size_t); StrBlobPtr &operator-=(size_t); StrBlobPtr operator+(size_t) const; //14.28 StrBlobPtr operator-(size_t) const; string& deref() const; StrBlobPtr& incr(); string& operator[](size_t n); //14.26 const string& operator[](size_t n) const; private: shared_ptr<vector<string>> check(size_t, const string&) const; weak_ptr<vector<string>> wptr; size_t curr; }; bool operator==(const StrBlobPtr&, const StrBlobPtr&); bool operator!=(const StrBlobPtr&, const StrBlobPtr&); bool operator<(const StrBlobPtr&, const StrBlobPtr&); bool operator>(const StrBlobPtr&, const StrBlobPtr&); bool operator<=(const StrBlobPtr&, const StrBlobPtr&); bool operator>=(const StrBlobPtr&, const StrBlobPtr&); inline string& StrBlobPtr::deref() const{ auto p = check(curr, "dereference past end"); return (*p)[curr]; } inline StrBlobPtr& StrBlobPtr::incr(){ check(curr, "increment past end of StrBlobPtr"); ++curr; return *this; } const string &StrBlobPtr::operator*() const{ //14.30 auto p = check(curr, "dereference past end"); return (*p)[curr]; } const string *StrBlobPtr::operator->() const{ return &this->operator*(); } inline StrBlobPtr &StrBlobPtr::operator++() { check(curr, "increment past end of StrBlobPtr"); ++curr; return *this; } inline StrBlobPtr &StrBlobPtr::operator--() { --curr; check(curr, "decrement past begin of StrBlobPtr"); 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+=(size_t n) { curr += n; check(curr, "increment past end of StrBlobPtr"); return *this; } inline StrBlobPtr &StrBlobPtr::operator-=(size_t n) { curr -= n; check(curr, "increment past end of StrBlobPtr"); return *this; } inline StrBlobPtr StrBlobPtr::operator+(size_t n) const { StrBlobPtr ret = *this; ret += n; return ret; } inline StrBlobPtr StrBlobPtr::operator-(size_t n) const { StrBlobPtr ret = *this; ret -= n; return ret; } inline shared_ptr<vector<string>> StrBlobPtr::check(size_t i, const string& msg) const{ auto ret = wptr.lock(); if (!ret) throw runtime_error("unbound StrBlobPtr"); if (i >= ret->size()) throw out_of_range(msg); return ret; } inline string& StrBlobPtr::operator[](size_t n){ auto p = check(n, "dereference out of range."); return (*p)[n]; } inline const string& StrBlobPtr::operator[](size_t n) const{ auto p = check(n, "dereference out of range."); return (*p)[n]; } //================================================================================= // // ConstStrBlobPtr - custom const_iterator of StrBlob // //================================================================================= 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&); public: ConstStrBlobPtr() : curr(0) {} ConstStrBlobPtr(const StrBlob& s, size_t sz = 0) : wptr(s.data), curr(sz) {} const string& deref() const; ConstStrBlobPtr& incr(); ConstStrBlobPtr &operator++(); //14.27 ConstStrBlobPtr &operator--(); ConstStrBlobPtr operator++(int); ConstStrBlobPtr operator--(int); ConstStrBlobPtr &operator+=(size_t); ConstStrBlobPtr &operator-=(size_t); ConstStrBlobPtr operator+(size_t) const; //14.28 ConstStrBlobPtr operator-(size_t) const; const string& operator[](size_t n) const; //14.26 const string& operator*() const; const string* operator->() const; //14.30 private: shared_ptr<vector<string>> check(size_t, const string&) const; weak_ptr<vector<string>> wptr; size_t curr; }; inline const string& ConstStrBlobPtr::deref() const{ auto p = check(curr, "dereference past end"); return (*p)[curr]; } inline ConstStrBlobPtr& ConstStrBlobPtr::incr(){ check(curr, "increment past end of StrBlobPtr"); ++curr; return *this; } inline const string& ConstStrBlobPtr::operator*() const { auto p = check(curr, "dereference past end"); return (*p)[curr]; } inline const string *ConstStrBlobPtr::operator->() const { //14.30 return &this->operator*(); } inline ConstStrBlobPtr &ConstStrBlobPtr::operator++() { check(curr, "increment past end of ConstStrBlobPtr"); ++curr; return *this; } inline ConstStrBlobPtr &ConstStrBlobPtr::operator--() { --curr; check(-1, "decrement past begin of ConstStrBlobPtr"); 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+=(size_t n) { curr += n; check(curr, "increment past end of ConstStrBlobPtr"); return *this; } inline ConstStrBlobPtr &ConstStrBlobPtr::operator-=(size_t n) { curr -= n; check(curr, "increment past end of ConstStrBlobPtr"); return *this; } inline ConstStrBlobPtr ConstStrBlobPtr::operator+(size_t n) const { ConstStrBlobPtr ret = *this; ret += n; return ret; } inline ConstStrBlobPtr ConstStrBlobPtr::operator-(size_t n) const { ConstStrBlobPtr ret = *this; ret -= n; return ret; } inline shared_ptr<vector<string>> ConstStrBlobPtr::check(size_t i, const string& msg) const{ auto ret = wptr.lock(); if (!ret) throw runtime_error("unbound StrBlobPtr"); if (i >= ret->size()) throw out_of_range(msg); return ret; } inline const string& ConstStrBlobPtr::operator[](size_t n) const{ auto p = check(n, "dereference out of range."); return (*p)[n]; } bool operator==(const ConstStrBlobPtr&, const ConstStrBlobPtr&); bool operator!=(const ConstStrBlobPtr&, const ConstStrBlobPtr&); bool operator<(const ConstStrBlobPtr&, const ConstStrBlobPtr&); bool operator>(const ConstStrBlobPtr&, const ConstStrBlobPtr&); bool operator<=(const ConstStrBlobPtr&, const ConstStrBlobPtr&); bool operator>=(const ConstStrBlobPtr&, const ConstStrBlobPtr&); //================================================================== // // operators // //================================================================== bool operator==(const StrBlob& lhs, const StrBlob& rhs){ return *lhs.data == *rhs.data; } bool operator!=(const StrBlob& lhs, const StrBlob& rhs){ return !(lhs == rhs); } bool operator<(const StrBlob& lhs, const StrBlob& rhs){ return lexicographical_compare(lhs.data->begin(), lhs.data->end(), rhs.data->begin(), rhs.data->end()); } bool operator>(const StrBlob& lhs, const StrBlob& rhs){ return rhs < lhs; } bool operator<=(const StrBlob& lhs, const StrBlob& rhs){ return !(lhs > rhs); } bool operator>=(const StrBlob& lhs, const StrBlob& rhs){ return !(lhs < rhs); } bool operator==(const StrBlobPtr& lhs, const StrBlobPtr& rhs){ return lhs.curr == rhs.curr; } bool operator!=(const StrBlobPtr& lhs, const StrBlobPtr& rhs){ return !(lhs == rhs); } bool operator<(const StrBlobPtr& x, const StrBlobPtr& y){ return x.curr < y.curr; } bool operator>(const StrBlobPtr& x, const StrBlobPtr& y){ return x.curr > y.curr; } bool operator<=(const StrBlobPtr& x, const StrBlobPtr& y){ return x.curr <= y.curr; } bool operator>=(const StrBlobPtr& x, const StrBlobPtr& y){ return x.curr >= y.curr; } bool operator==(const ConstStrBlobPtr& lhs, const ConstStrBlobPtr& rhs){ return lhs.curr == rhs.curr; } bool operator!=(const ConstStrBlobPtr& lhs, const ConstStrBlobPtr& rhs){ return !(lhs == rhs); } bool operator<(const ConstStrBlobPtr& lhs, const ConstStrBlobPtr& rhs){ return lhs.curr < rhs.curr; } bool operator>(const ConstStrBlobPtr& lhs, const ConstStrBlobPtr& rhs){ return lhs.curr > rhs.curr; } bool operator<=(const ConstStrBlobPtr& lhs, const ConstStrBlobPtr& rhs){ return lhs.curr <= rhs.curr; } bool operator>=(const ConstStrBlobPtr& lhs, const ConstStrBlobPtr& rhs){ return lhs.curr >= rhs.curr; } //================================================================== // // copy assignment operator and move assignment operator. // //================================================================== StrBlob& StrBlob::operator=(const StrBlob& lhs){ data = make_shared<vector<string>>(*lhs.data); return *this; } StrBlob& StrBlob::operator=(StrBlob&& rhs) noexcept{ if (this != &rhs) { data = move(rhs.data); rhs.data = nullptr; } return *this; } //================================================================== // // members // //================================================================== StrBlobPtr StrBlob::begin(){ return StrBlobPtr(*this); } StrBlobPtr StrBlob::end(){ return StrBlobPtr(*this, data->size()); } ConstStrBlobPtr StrBlob::cbegin() const{ return ConstStrBlobPtr(*this); } ConstStrBlobPtr StrBlob::cend() const{ return ConstStrBlobPtr(*this, data->size()); } //StrVec class StrVec { friend bool operator==(const StrVec&, const StrVec&); friend bool operator!=(const StrVec&, const StrVec&); friend bool operator<(const StrVec&, const StrVec&); friend bool operator>(const StrVec&, const StrVec&); friend bool operator<=(const StrVec&, const StrVec&); friend bool operator>=(const StrVec&, const StrVec&); public: StrVec() : elements(nullptr), first_free(nullptr), cap(nullptr) {} StrVec(initializer_list<string>); StrVec(const StrVec&); StrVec& operator=(const StrVec&); StrVec(StrVec&&) noexcept; StrVec& operator=(StrVec&&) noexcept; ~StrVec(); StrVec& operator=(initializer_list<string>); //14.23 void push_back(const string&); size_t size() const { return first_free - elements; } size_t capacity() const { return cap - elements; } string* begin() const { return elements; } string* end() const { return first_free; } string& at(size_t pos) { return *(elements + pos); } const string& at(size_t pos) const { return *(elements + pos); } string& operator[](size_t n) { return elements[n]; } //14.26 const string& operator[](size_t n) const { return elements[n]; } //14.26 void reserve(size_t new_cap); void resize(size_t count); void resize(size_t count, const string&); private: pair<string*, string*> alloc_n_copy(const string*, const string*); void free(); void chk_n_alloc() { if (size() == capacity()) reallocate(); } void reallocate(); void alloc_n_move(size_t new_cap); void range_initialize(const string*, const string*); private: string* elements; string* first_free; string* cap; allocator<string> alloc; }; bool operator==(const StrVec&, const StrVec&); bool operator!=(const StrVec&, const StrVec&); bool operator<(const StrVec&, const StrVec&); bool operator>(const StrVec&, const StrVec&); bool operator<=(const StrVec&, const StrVec&); bool operator>=(const StrVec&, const StrVec&); void StrVec::push_back(const string& s){ chk_n_alloc(); alloc.construct(first_free++, s); } pair<string*, string*> StrVec::alloc_n_copy(const string* b, const string* e){ auto data = alloc.allocate(e - b); return {data, uninitialized_copy(b, e, data)}; } void StrVec::free(){ if (elements) { for_each(elements, first_free, [this](string& rhs) { alloc.destroy(&rhs); }); alloc.deallocate(elements, cap - elements); } } void StrVec::range_initialize(const string* first, const string* last){ auto newdata = alloc_n_copy(first, last); elements = newdata.first; first_free = cap = newdata.second; } StrVec::StrVec(const StrVec& rhs){ range_initialize(rhs.begin(), rhs.end()); } StrVec::StrVec(initializer_list<string> il){ range_initialize(il.begin(), il.end()); } StrVec::~StrVec(){ free(); } StrVec& StrVec::operator=(const StrVec& rhs){ auto data = alloc_n_copy(rhs.begin(), rhs.end()); free(); elements = data.first; first_free = cap = data.second; return *this; } void StrVec::alloc_n_move(size_t new_cap){ auto newdata = alloc.allocate(new_cap); auto dest = newdata; auto elem = elements; for (size_t i = 0; i != size(); ++i) alloc.construct(dest++, move(*elem++)); free(); elements = newdata; first_free = dest; cap = elements + new_cap; } void StrVec::reallocate(){ auto newcapacity = size() ? 2 * size() : 1; alloc_n_move(newcapacity); } void StrVec::reserve(size_t new_cap){ if (new_cap <= capacity()) return; alloc_n_move(new_cap); } void StrVec::resize(size_t count){ resize(count, string()); } void StrVec::resize(size_t count, const string& s){ if (count > size()) { if (count > capacity()) reserve(count * 2); for (size_t i = size(); i != count; ++i) alloc.construct(first_free++, s); } else if (count < size()) { while (first_free != elements + count) alloc.destroy(--first_free); } } StrVec::StrVec(StrVec&& s) noexcept : elements(s.elements), first_free(s.first_free), cap(s.cap){ // leave s in a state in which it is safe to run the destructor. s.elements = s.first_free = s.cap = nullptr; } StrVec& StrVec::operator=(StrVec&& rhs) noexcept{ if (this != &rhs) { free(); elements = rhs.elements; first_free = rhs.first_free; cap = rhs.cap; rhs.elements = rhs.first_free = rhs.cap = nullptr; } return *this; } bool operator==(const StrVec& lhs, const StrVec& rhs){ return (lhs.size() == rhs.size() && equal(lhs.begin(), lhs.end(), rhs.begin())); } bool operator!=(const StrVec& lhs, const StrVec& rhs){ return !(lhs == rhs); } bool operator<(const StrVec& lhs, const StrVec& rhs){ return lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end()); } bool operator>(const StrVec& lhs, const StrVec& rhs){ return rhs < lhs; } bool operator<=(const StrVec& lhs, const StrVec& rhs){ return !(rhs < lhs); } bool operator>=(const StrVec& lhs, const StrVec& rhs){ return !(lhs < rhs); } StrVec& StrVec::operator=(initializer_list<string> li){ //14.23 auto data = alloc_n_copy(li.begin(), li.end()); free(); elements = data.first; first_free = cap = data.second; return *this; } //14.24 class Date { friend bool operator==(const Date& lhs, const Date& rhs); friend bool operator<(const Date& lhs, const Date& rhs); friend bool check(const Date& d); friend ostream& operator<<(ostream& os, const Date& d); public: typedef size_t Size; //! default constructor Date() = default; //! constructor taking Size as days explicit Date(Size days); //! constructor taking three Size Date(Size d, Size m, Size y) : day(d), month(m), year(y) {} //! constructor taking iostream Date(istream& is, ostream& os); //! copy constructor Date(const Date& d); //! move constructor Date(Date&& d) noexcept; //! copy operator= Date& operator=(const Date& d); //! move operator= Date& operator=(Date&& rhs) noexcept; //! destructor -- in this case, user-defined destructor is not nessary. ~Date() { cout << "destroying\n"; } //! members Size toDays() const; // not implemented yet. Date& operator+=(Size offset); Date& operator-=(Size offset); explicit operator bool() { return (year < 4000) ? true : false; } //14.49 private: Size day = 1; Size month = 1; Size year = 0; }; static const Date::Size YtoD_400 = 146097; // 365*400 + 400/4 -3 == 146097 static const Date::Size YtoD_100 = 36524; // 365*100 + 100/4 -1 == 36524 static const Date::Size YtoD_4 = 1461; // 365*4 + 1 == 1461 static const Date::Size YtoD_1 = 365; // 365 //! normal year static const vector<Date::Size> monthsVec_n = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; //! leap year static const vector<Date::Size> monthsVec_l = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; //! non-member operators: << >> - == != < <= > >= //! ostream& operator<<(ostream& os, const Date& d); istream& operator>>(istream& is, Date& d); int operator-(const Date& lhs, const Date& rhs); bool operator==(const Date& lhs, const Date& rhs); bool operator!=(const Date& lhs, const Date& rhs); bool operator<(const Date& lhs, const Date& rhs); bool operator<=(const Date& lhs, const Date& rhs); bool operator>(const Date& lhs, const Date& rhs); bool operator>=(const Date& lhs, const Date& rhs); Date operator-(const Date& lhs, Date::Size rhs); Date operator+(const Date& lhs, Date::Size rhs); //! utillities: bool check(const Date& d); inline bool isLeapYear(Date::Size y); //! check if the date object passed in is valid inline bool check(const Date& d){ if (d.month == 0 || d.month > 12) return false; else { //! month == 1 3 5 7 8 10 12 if (d.month == 1 || d.month == 3 || d.month == 5 || d.month == 7 || d.month == 8 || d.month == 10 || d.month == 12) { if (d.day == 0 || d.day > 31) return false; else return true; } else { //! month == 4 6 9 11 if (d.month == 4 || d.month == 6 || d.month == 9 || d.month == 11) { if (d.day == 0 || d.day > 30) return false; else return true; } else { //! month == 2 if (isLeapYear(d.year)) { if (d.day == 0 || d.day > 29) return false; else return true; } else { if (d.day == 0 || d.day > 28) return false; else return true; } } } } } inline bool isLeapYear(Date::Size y){ if (!(y % 400)) { return true; } else { if (!(y % 100)) { return false; } else return !(y % 4); } } //! constructor taking Size as days //! the argument must be within (0, 2^32) Date::Date(Size days){ //! calculate the year Size y400 = days / YtoD_400; Size y100 = (days - y400 * YtoD_400) / YtoD_100; Size y4 = (days - y400 * YtoD_400 - y100 * YtoD_100) / YtoD_4; Size y = (days - y400 * YtoD_400 - y100 * YtoD_100 - y4 * YtoD_4) / 365; Size d = days - y400 * YtoD_400 - y100 * YtoD_100 - y4 * YtoD_4 - y * 365; this->year = y400 * 400 + y100 * 100 + y4 * 4 + y; //! check if leap and choose the months vector accordingly vector<Size> currYear = isLeapYear(this->year) ? monthsVec_l : monthsVec_n; //! calculate day and month using find_if + lambda Size D_accumu = 0, M_accumu = 0; //! @bug fixed: the variabbles above hade been declared inside the //! find_if as static //! which caused the bug. It works fine now after being move //! outside. find_if(currYear.cbegin(), currYear.cend(), [&](Size m) { D_accumu += m; M_accumu++; if (d < D_accumu) { this->month = M_accumu; this->day = d + m - D_accumu; return true; } else return false; }); } //! construcotr taking iostream Date::Date(istream& is, ostream& os){ is >> day >> month >> year; if (is) { if (check(*this)) return; else { os << "Invalid input! Object is default initialized."; *this = Date(); } } else { os << "Invalid input! Object is default initialized."; *this = Date(); } } //! copy constructor Date::Date(const Date& d) : day(d.day), month(d.month), year(d.year){ } //! move constructor Date::Date(Date&& d) noexcept : day(d.day), month(d.month), year(d.year){ cout << "copy moving"; } //! copy operator= Date& Date::operator=(const Date& d){ this->day = d.day; this->month = d.month; this->year = d.year; return *this; } //! move operator= Date& Date::operator=(Date&& rhs) noexcept{ if (this != &rhs) { this->day = rhs.day; this->month = rhs.month; this->year = rhs.year; } cout << "moving ="; return *this; } //! conver to days Date::Size Date::toDays() const{ Size result = this->day; //! check if leap and choose the months vector accordingly vector<Size> currYear = isLeapYear(this->year) ? monthsVec_l : monthsVec_n; //! calculate result + days by months for (auto it = currYear.cbegin(); it != currYear.cbegin() + this->month - 1; ++it) result += *it; //! calculate result + days by years result += (this->year / 400) * YtoD_400; result += (this->year % 400 / 100) * YtoD_100; result += (this->year % 100 / 4) * YtoD_4; result += (this->year % 4) * YtoD_1; return result; } //! member operators: += -= Date& Date::operator+=(Date::Size offset){ *this = Date(this->toDays() + offset); return *this; } Date& Date::operator-=(Date::Size offset) { if (this->toDays() > offset) *this = Date(this->toDays() - offset); else *this = Date(); return *this; } //! non-member operators: << >> - == != < <= > >= ostream& operator<<(ostream& os, const Date& d){ os << d.day << " " << d.month << " " << d.year; return os; } istream& operator>>(istream& is, Date& d){ if (is) { Date input = Date(is, cout); if (check(input)) d = input; } return is; } int operator-(const Date& lhs, const Date& rhs){ return lhs.toDays() - rhs.toDays(); } bool operator==(const Date& lhs, const Date& rhs){ return (lhs.day == rhs.day) && (lhs.month == rhs.month) && (lhs.year == rhs.year); } bool operator!=(const Date& lhs, const Date& rhs){ return !(lhs == rhs); } bool operator<(const Date& lhs, const Date& rhs){ return lhs.toDays() < rhs.toDays(); } bool operator<=(const Date& lhs, const Date& rhs){ return (lhs < rhs) || (lhs == rhs); } bool operator>(const Date& lhs, const Date& rhs){ return !(lhs <= rhs); } bool operator>=(const Date& lhs, const Date& rhs){ return !(lhs < rhs); } Date operator-(const Date& lhs, Date::Size rhs){ //! ^^^ rhs must not be larger than 2^32-1 //! copy lhs Date result(lhs); result -= rhs; return result; } Date operator+(const Date& lhs, Date::Size rhs){ //! ^^^ rhs must not be larger than 2^32-1 //! copy lhs Date result(lhs); result += rhs; return result; } //14.32 class StrBlobPtr_pointer { public: StrBlobPtr_pointer() = default; StrBlobPtr_pointer(StrBlobPtr* p) : pointer(p) {} StrBlobPtr& operator*(); StrBlobPtr* operator->(); private: StrBlobPtr* pointer = nullptr; }; StrBlobPtr& StrBlobPtr_pointer::operator*(){ return *(this->pointer); } StrBlobPtr* StrBlobPtr_pointer::operator->(){ return &this -> operator*(); } //14.34 struct func_class{ int operator()(bool a, int b, int c){ return a ? b : c; } }; //14.35 class PrintString{ public: PrintString(istream& i = cin) : is(i){} string operator()(){ string str; getline(is, str); return is ? str : string(); } private: istream& is; }; //14.37 class IsEqual { int value; public: IsEqual(int v) : value(v) {} bool operator()(int elem) { return elem == value; } }; //14.38 class BoundTest { public: BoundTest(size_t l = 0, size_t u = 0) : lower(l), upper(u) {} bool operator()(const string& s) { return lower <= s.length() && s.length() <= upper; } private: size_t lower; size_t upper; }; //14.40 class ShorterString { public: bool operator()(string const& s1, string const& s2) const { return s1.size() < s2.size(); } }; class BiggerEqual { size_t sz_; public: BiggerEqual(size_t sz) : sz_(sz) {} bool operator()(string const& s) { return s.size() >= sz_; } }; class Print { public: void operator()(string const& s) { cout << s << " "; } }; string make_plural(size_t ctr, string const& word, string const& ending){ return (ctr > 1) ? word + ending : word; } void elimDups(vector<string>& words){ sort(words.begin(), words.end()); auto end_unique = unique(words.begin(), words.end()); words.erase(end_unique, words.end()); } void biggies(vector<string>& words, vector<string>::size_type sz){ elimDups(words); stable_sort(words.begin(), words.end(), ShorterString()); auto wc = find_if(words.begin(), words.end(), BiggerEqual(sz)); auto count = words.end() - wc; cout << count << " " << make_plural(count, "word", "s") << " of length " << sz << " or longer" << endl; for_each(wc, words.end(), Print()); cout << endl; } #endif
//main.cc #include <fstream> #include <iostream> #include <vector> #include <functional> #include <map> #include "Chapter14.h" using namespace std; #define NUM1452 /*14.16*/ void foo(String x){ cout << x << endl; } void bar(const String& x){ cout << x.c_str() << endl; } String baz(){ String ret("world"); return ret; } //14.44 //! normal function int add(int i, int j) { return i + j; } //! named lambda auto mod = [](int i, int j) { return i % j; }; //! functor struct wy_div { int operator()(int denominator, int divisor) { return denominator / divisor; } }; //! the map map<string, function<int(int, int)>> binops = { {"+", add}, // function pointer {"-", minus<int>()}, // library functor {"/", wy_div()}, // user-defined functor {"*", [](int i, int j) { return i * j; }}, // unnamed lambda {"%", mod} // named lambda object }; int main(){ /*14.1*/ #ifdef NUM141 cout <<"不同,1. 我们可以直接调用重载运算符函数。2.重载运算符函数必须是类的成员,或者至少有一个类类型的参数." "重载运算符不保证操作数的求值顺序,例如对&&和||的重载版本不再具有'短路求值'的特性,两个操作数都要求值,而且不规定操作数的求值顺序。" "相同。重载运算符与内置运算符有一样的优先性和结合性。"<<endl; #endif /*14.2*/ #ifdef NUM142 Sales_data item; cin >> item; cout << item << endl; #endif /*14.3*/ #ifdef NUM143 cout <<"(a)string字符类型是const char[]类型,char*类型内置了==运算符,所以不会调用string类型的==重载. " "(b)string版本 (c)vector版本 (d)string版本"<<endl; #endif /*14.4*/ #ifdef NUM144 cout <<"(a)对称操作符,不需要是成员.(b)改变对象的状态,必须是成员" "(c)改变对象状态,必须是成员(d)必须是成员(e)非成员(f)非成员(g)非成员(h)必须是成员" <<endl; #endif /*14.5*/ #ifdef NUM145 Book book1(123, "C++","Lippman","2013"); Book book2(123, "C++","Lippman","2013"); if(book1 == book2) cout << book1 << endl; #endif /*14.6*/ #ifdef NUM146 cout << "见Chapter14.h //14.2"<<endl; #endif /*14.7*/ #ifdef NUM147 String str("hello world"); cout << str << endl; #endif /*14.8*/ #ifdef NUM148 cout << "见Chapter14.h //14.5"<<endl; #endif /*14.10*/ #ifdef NUM1410 cout << "见Chapter14.h //14.2"<<endl; #endif /*14.10*/ #ifdef NUM1410 cout <<"(a)正确的形式 (b)24.95转换成unsigned类型,错误,输出10 24 22.8 0.95. "<<endl; #endif /*14.11*/ #ifdef NUM1411 cout <<"只是没有添加输入检查,没有什么发生. "<<endl; #endif /*14.12*/ #ifdef NUM1412 cout << "见Chapter14.h //14.5"<<endl; #endif /*14.13*/ #ifdef NUM1413 cout << "不需要"<<endl; #endif /*14.14*/ #ifdef NUM1414 /* Sales_data operator+(const Sales_data &lhs, const Sales_data &rhs){ Sales_data sum = lhs; // copy data members from lhs into sum sum = sum + rhs; // add rhs into sum return sum; } */ cout << "如上所示,直接定义opeartor+会拷贝一个不必要的临时对象。"<<endl; #endif /*14.15*/ #ifdef NUM1415 cout << "见Chapter14.h //14.5"<<endl; #endif /*14.16*/ #ifdef NUM1416 //StrBlob StrBlobPtr StrBlob sb{"Hello", "World", "C++"}; for (ConstStrBlobPtr iter = sb.cbegin(); iter != sb.cend(); iter.incr()) { cout << iter.deref() << " "; } cout << endl; //StrVec StrVec vec; vec.reserve(6); cout << "capacity(reserve to 6): " << vec.capacity() << endl; vec.reserve(4); cout << "capacity(reserve to 4): " << vec.capacity() << endl; vec.push_back("hello"); vec.push_back("world"); vec.resize(4); for (auto i = vec.begin(); i != vec.end(); ++i) cout << *i << endl; cout << "-EOF-" << endl; vec.resize(1); for (auto i = vec.begin(); i != vec.end(); ++i) cout << *i << endl; cout << "-EOF-" << endl; StrVec vec_list{"hello", "world", "C++"}; for (auto i = vec_list.begin(); i != vec_list.end(); ++i) cout << *i << " "; cout << endl; // Test operator== const StrVec const_vec_list{"hello", "world", "C++"}; if (vec_list == const_vec_list) for (const auto& str : const_vec_list) cout << str << " "; cout << endl; //string 见14.7 char text[] = "world"; String s0; String s1("hello"); String s2(move(s0)); String s3 = s1; String s4(text); s2 = s1; if (s2 == s1) cout << "s2 == s1" << endl; foo(s1); bar(s1); foo("temporary"); bar("temporary"); String s5 = baz(); vector<String> svec; // svec.push_back(s0); svec.push_back(s1); svec.push_back(s2); svec.push_back(s3); svec.push_back(s4); svec.push_back(baz()); svec.push_back("good job"); for (const auto& s : svec) { cout << s << endl; } cout << "Input a string: "; String s6; cin >> s6; cout << s6 << endl; #endif /*14.17*/ #ifdef NUM1417 cout << "需要,见Chapter14.h //14.15"<<endl; #endif /*14.18*/ #ifdef NUM1418 //StrBlob StrBlob str1{"a","b","c"}; StrBlob str2{"a","b","c"}; if(str1 >= str2){ for(ConstStrBlobPtr iter = str1.cbegin(); iter != str1.cend(); iter.incr()) cout<< iter.deref()<< " "; cout << endl; } //StrVec const StrVec const_vec_list{"hello", "world", "ok"}; const StrVec const_vec_list_small{"hello", "world", "linux"}; cout << (const_vec_list_small < const_vec_list) << endl; //String String s1("hello"); cout << "Input a string: "; String s6; cin >> s6; cout << s6 << endl; if (s6 > s1) cout << "s6 > s1" << endl; #endif /*14.19*/ #ifdef NUM1419 cout << "需要,见Chapter14.h //14.5"<<endl; #endif /*14.20*/ #ifdef NUM1420 cout << "见Chapter14.h //14.2"<<endl; #endif /*14.21*/ #ifdef NUM1421 /* Sales_data& Sales_data::operator+=(const Sales_data &rhs) { Sales_data old_data = *this; *this = old_data + rhs; return *this; } Sales_data operator+(const Sales_data &lhs, const Sales_data &rhs) { Sales_data sum; sum.units_sold = lhs.units_sold + rhs.units_sold; sum.revenue = lhs.revenue + rhs.revenue; return sum; } */ cout << "如上所示,+和+= 的运算符操作都定义了一个不必要的Sales_data对象。"<<endl; #endif /*14.22*/ #ifdef NUM1422 string strCp5("C++ Primer"); Sales_data cp5 = strCp5; cout << cp5 << endl; #endif /*14.23*/ #ifdef NUM1423 const StrVec const_vec_list_small = {"hello", "world", "c++"}; for(auto &i: const_vec_list_small) cout << i << " "; cout <<endl; #endif /*14.24*/ #ifdef NUM1424 Date lhs(9999999), rhs(1); cout << (lhs -= 12000) << "\n"; #endif /*14.25*/ #ifdef NUM1425 cout <<"无需其他,见14.24"<<endl; #endif /*14.26*/ #ifdef NUM1426 //StrBlob StrBlob sb1{"a", "b", "c"}; StrBlob sb2 = sb1; sb2[2] = "abc"; if (sb1 > sb2) { for (ConstStrBlobPtr iter = sb1.cbegin(); iter < sb1.cend(); iter.incr()) cout << iter.deref() << " "; cout << endl; } StrBlobPtr iter(sb2); cout << iter[2] << endl; //StrVec const StrVec const_vec_list_small{"hello", "world", "ok"}; cout << const_vec_list_small[1] << endl; //String String s1("hello"); cout << s1[2] << endl; #endif /*14.27*/ #ifdef NUM1427 StrBlob sb1{"a", "b", "c"}; StrBlob sb2 = sb1; sb2[2] = "abc"; if (sb1 > sb2) { for (StrBlobPtr iter = sb1.begin(); iter < sb1.end(); ++iter) cout << iter.deref() << " "; cout << endl; } ConstStrBlobPtr iter(sb2); cout << (iter + 2).deref() << endl; #endif /*14.28*/ #ifdef NUM1428 cout << "见Chapter14.h //14.27"<<endl; #endif /*14.29*/ #ifdef NUM1429 cout <<"因为++ -- 改变了对象的状态,定义const版本是没有意义的. "<<endl; #endif /*14.30*/ #ifdef NUM1430 StrBlob sb1{"a", "b", "c"}; StrBlob sb2 = sb1; StrBlobPtr iter1(sb1); ConstStrBlobPtr iter2(sb2); cout << *(iter1+2) << " "<< iter2->size() << endl; #endif /*14.31*/ #ifdef NUM1431 cout<< "StrBlobPtrde类中被北邮动态内存分配,所以只需要合成的析构函数. 并且, 两个成员weak_ptr<vector<string>>和size_t类型,前者定义了自己的拷贝构造函数,后者是内置类型。所以完全可以利用合成的拷贝控制。"<<endl; #endif /*14.32*/ #ifdef NUM1432 StrBlob sb1{"a", "b", "c"}; StrBlob sb2 = sb1; StrBlobPtr iter1(sb1); StrBlobPtr_pointer it(&iter1); cout << it->deref() <<endl; #endif /*14.33*/ #ifdef NUM1433 cout <<"一个重载操作符函数与操作符相同数量的参数。因此,最小0最大256."<<endl; #endif /*14.34*/ #ifdef NUM1434 func_class fc; cout << fc(0, 1, 2) << endl; #endif /*14.35*/ #ifdef NUM1435 PrintString getstr; cout << getstr() << endl; #endif /*14.36*/ #ifdef NUM1436 PrintString getInput; vector<string> vec; for (string tmp; !(tmp = getInput()).empty();) vec.push_back(tmp); for (const auto& str : vec) cout << str << " "; cout << endl; #endif /*14.37*/ #ifdef NUM1437 vector<int> vec = {3, 2, 1, 4, 3, 7, 8, 6}; replace_if(vec.begin(), vec.end(), IsEqual(3), 5); for (int i : vec) cout << i << " "; cout << endl; #endif /*14.38*/ #ifdef NUM1438 ifstream fin("./storyDataFile"); size_t quantity9 = 0, quantity10 = 0; BoundTest test9(1, 9); BoundTest test10(1, 10); for (string word; fin >> word;) { if (test9(word)) ++quantity9; if (test10(word)) ++quantity10; } cout << quantity9 << ", " << quantity10 << endl; #endif /*14.39*/ #ifdef NUM1439 cout<<"见14.38"<<endl; #endif /*14.40*/ #ifdef NUM1440 vector<string> vec{"fox", "jumps", "over", "quick", "red", "red", "slow", "the", "turtle"}; biggies(vec, 4); #endif /*14.41*/ #ifdef NUM1441 cout <<"lambda是通过匿名的函数对象来实现的,因此我们可以把lambda看作是对函数对象在使用方式上进行的简化。" "当代码需要一个简单的函数,并且这个函数并不会在其他地方被使用时,就可以使用lambda来实现," "此时它所起的作用类似于匿名函数。但如果这个函数需要多次使用,并且它需要保存某些状态的话,使用函数对象更合适一些。"<<endl; #endif /*14.42*/ #ifdef NUM1442 using placeholders::_1; vector<int> ivec{1, 111, 1111, 11111}; int count = count_if(ivec.cbegin(), ivec.cend(), bind(greater<int>(), _1, 1024)); cout << count << endl; vector<string> svec{"pooh", "pooh", "linux", "pooh"}; auto found = find_if(svec.cbegin(), svec.cend(), bind(not_equal_to<string>(), _1, "pooh")); cout << *found << endl; transform(ivec.begin(), ivec.end(), ivec.begin(), //all numbers multiple 2 bind(multiplies<int>(), _1, 2)); for (int i : ivec) cout << i << " "; cout << endl; #endif /*14.43*/ #ifdef NUM1443 auto data = {2, 3, 4, 5}; int input; cin >> input; modulus<int> mod; auto predicator = [&](int i) { return 0 == mod(input, i); }; auto is_divisible = any_of(data.begin(), data.end(), predicator); cout << (is_divisible ? "Yes!" : "No!") << endl; #endif /*14.44*/ #ifdef NUM1444 while (true) { cout << "\npleasr enter: num operator num :\n"; int n1, n2; string s; cin >> n1 >> s >> n2; cout << binops[s](n1, n2); } #endif /*14.45*/ #ifdef NUM1445 Sales_data cp5("C++ Primer 5th", 4, 106.5); cout << cp5 << endl; cout << static_cast<string>(cp5) << endl; //C++ Primer 5th cout << static_cast<double>(cp5) << endl; //106.5 #endif /*14.46*/ #ifdef NUM1446 cout <<"不应该,这种操作极具误导性,应该把它们声明成explicit的,这样可以防止sales_data" " 在默写情况下被默认转换成string或double类型,防止隐式的类型转换。"<<endl; #endif /*14.47*/ #ifdef NUM1447 struct Integral { operator const int(); // 转换成const int类型,编译器一般忽略,没有意义 operator int() const; //转换成int类型时,操作符不会改变对象的状态 }; #endif /*14.48*/ #ifdef NUM1448 cout <<"定义bool类型转换的运算符是有用处的,但是必须是explicit,防止自动类型转换。" #endif /*14.49*/ #ifdef NUM1449 Date date(12, 4, 2015); if (static_cast<bool>(date)) cout << date << endl; #endif /*14.50*/ #ifdef NUM1450 struct LongDouble { LongDouble(double = 0.0); operatordouble(); operatorfloat(); }; LongDouble ldObj; int ex1 = ldObj; // error ambiguous: double or float? float ex2 = ldObj; // legal #endif /*14.51*/ #ifdef NUM1451 void calc(int); void calc(LongDouble); double dval; calc(dval); // which calc? cout<< "最佳可行函数: void calc(int).因为类类型转换时最低级别. " "顺序是1. 完全匹配. 2. const转换. 3. 类型提升 4.算数和指针转换 5.类类型转换. "<<endl; #endif /*14.52*/ #ifdef NUM1452 struct LongDouble { LongDouble operator+(const SmallInt&); // 1 }; LongDouble operator+(LongDouble&, double); // 2 SmallInt si; LongDouble ld; ld = si + ld; //不合法,无论哪个版本,+号两边值都要转换. ld = ld + si; //1精确匹配 #endif /*14.53*/ #ifdef NUM1453 SmallInt s1; double d = s1 + 3.14; ambiguous. Fixed: SmallInt s1; double d = s1 + SmallInt(3.14); cout<<"内置的operator+(int, double)是可行的,而3.14可以转换为int,然后再转换为SmallInt,所以SmallInt的成员operator+也是可行的。两者都需要进行类型转换,所以会产生二义性。改为:double d = s1 +Smallint(3.14);即可" <<endl; #endif return 0; }
参考资料:
c++ primer中文版第五版,电子工业出版社。
c++ primer第四版习题解答,人民邮电出版社。
[email protected]://github.com/pezy/CppPrimer
时间: 2024-10-27 13:27:30