【C++】重载运算符(二)
1.4 下标运算符p501
- 下标运算符必须是成员函数,表示容器的类通常可以通过容器中的位置访问元素,定义下标运算符operator[]
- 一个包含下标运算符的类,通常,定义2个版本:一个返回普通引用,另一个是类的常量成员引用
P14.26
StrBlob
& StrBlobPtr
,实例
#include <vector>
using std::vector;#include <string>
using std::string;#include <initializer_list>
using std::initializer_list;#include <memory>
using std::make_shared; using std::shared_ptr;#include <exception>#ifndef _MSC_VER
#define NOEXCEPT noexcept
#else
#define NOEXCEPT
#endifclass 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(std::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(std::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 std::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) { }string& deref() const;StrBlobPtr& incr();string& operator[](size_t n);const string& operator[](size_t n) const;private:shared_ptr<vector<string>> check(size_t, const string&) const;std::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;
}inline shared_ptr<vector<string>> StrBlobPtr::check(size_t i, const string &msg) const
{auto ret = wptr.lock();if (!ret) throw std::runtime_error("unbound StrBlobPtr");if (i >= ret->size()) throw std::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();const string& operator[](size_t n) const;private:std::shared_ptr<vector<string>> check(size_t, const string&) const;std::weak_ptr<vector<string>> wptr;size_t curr;
};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&);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 std::shared_ptr<vector<string>> ConstStrBlobPtr::check(size_t i, const string &msg) const
{auto ret = wptr.lock();if (!ret) throw std::runtime_error("unbound StrBlobPtr");if (i >= ret->size()) throw std::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];
}#endif //CP5_STRBLOB_H_
#include "ex14_26_StrBlob.h"
#include <algorithm>//==================================================================
//
// StrBlob - 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 std::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 !(rhs < lhs);
}bool operator>=(const StrBlob &lhs, const StrBlob &rhs)
{return !(lhs < rhs);
}//================================================================
//
// StrBlobPtr - operators
//
//================================================================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;
}//================================================================
//
// ConstStrBlobPtr - operators
//
//================================================================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 = std::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());
}
#include "ex14_26_StrBlob.h"
#include <iostream>int main()
{StrBlob sb1{ "a", "b", "c" };StrBlob sb2 = sb1;sb2[2] = "b";if (sb1 > sb2) {for (ConstStrBlobPtr iter = sb1.cbegin(); iter < sb1.cend(); iter.incr())std::cout << iter.deref() << " ";std::cout << std::endl;}StrBlobPtr iter(sb2);std::cout << iter[2] << std::endl;
}
StrVec 实例
#include <memory>
#include <string>
#include <initializer_list>#ifndef _MSC_VER
#define NOEXCEPT noexcept
#else
#define NOEXCEPT
#endifclass 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(std::initializer_list<std::string>);StrVec(const StrVec&);StrVec& operator=(const StrVec&);StrVec(StrVec&&) NOEXCEPT;StrVec& operator=(StrVec&&)NOEXCEPT;~StrVec();void push_back(const std::string&);size_t size() const { return first_free - elements; }size_t capacity() const { return cap - elements; }std::string *begin() const { return elements; }std::string *end() const { return first_free; }std::string& at(size_t pos) { return *(elements + pos); }const std::string& at(size_t pos) const { return *(elements + pos); }std::string& operator[](size_t n) { return elements[n]; }const std::string& operator[](size_t n) const { return elements[n]; }void reserve(size_t new_cap);void resize(size_t count);void resize(size_t count, const std::string&);private:std::pair<std::string*, std::string*> alloc_n_copy(const std::string*, const std::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 std::string*, const std::string*);private:std::string *elements;std::string *first_free;std::string *cap;std::allocator<std::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&);
#include "ex14_26_StrVec.h"
#include <algorithm> // for_each, equalvoid StrVec::push_back(const std::string &s)
{chk_n_alloc();alloc.construct(first_free++, s);
}std::pair<std::string*, std::string*>
StrVec::alloc_n_copy(const std::string *b, const std::string *e)
{auto data = alloc.allocate(e-b);return { data, std::uninitialized_copy(b, e, data) };
}void StrVec::free()
{if (elements) {for_each(elements, first_free, [this](std::string &rhs){ alloc.destroy(&rhs); });alloc.deallocate(elements, cap - elements);}
}void StrVec::range_initialize(const std::string *first, const std::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(std::initializer_list<std::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++, std::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, std::string());
}void StrVec::resize(size_t count, const std::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() && std::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 std::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);
}
#include "ex14_26_StrVec.h"
#include <iostream>
#include <vector>int main()
{StrVec vec;vec.reserve(6);std::cout << "capacity(reserve to 6): " << vec.capacity() << std::endl;vec.reserve(4);std::cout << "capacity(reserve to 4): " << vec.capacity() << std::endl;vec.push_back("hello");vec.push_back("world");vec.resize(4);for (auto i = vec.begin(); i != vec.end(); ++i)std::cout << *i << std::endl;std::cout << "-EOF-" << std::endl;vec.resize(1);for (auto i = vec.begin(); i != vec.end(); ++i)std::cout << *i << std::endl;std::cout << "-EOF-" << std::endl;StrVec vec_list{ "hello", "world", "pezy" };for (auto i = vec_list.begin(); i != vec_list.end(); ++i)std::cout << *i << " ";std::cout << std::endl;// Test operator==const StrVec const_vec_list{ "hello", "world", "pezy" };if (vec_list == const_vec_list)for (const auto &str : const_vec_list)std::cout << str << " ";std::cout << std::endl;// Test operator<const StrVec const_vec_list_small{ "hello", "pezy", "ok" };std::cout << (const_vec_list_small < const_vec_list) << std::endl;// Test []std::cout << const_vec_list_small[1] << std::endl;
}
String 实例
#ifndef CP5_STRING_H__
#define CP5_STRING_H__#include <memory>
#include <iostream>#ifndef _MSC_VER
#define NOEXCEPT noexcept
#else
#define NOEXCEPT
#endif//===================================================================================
//
// |s|t|r|i|n|g|\0|-------------------|
// ^ ^ ^ first_free ^
// elements last_elem cap
//
//===================================================================================class String
{friend std::ostream& operator<<(std::ostream&, const String&);friend std::istream& operator>>(std::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]; }const char& operator[](size_t n) const { return elements[n]; }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:std::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;std::allocator<char> alloc;
};std::ostream& operator<<(std::ostream&, const String&);
std::istream& operator>>(std::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&);#endif
#include "ex14_26_String.h"
#include <algorithm>//===========================================================================
//
// operator - friend
//
//===========================================================================std::ostream& operator<<(std::ostream &os, const String &lhs)
{os << lhs.c_str();return os;
}std::istream& operator>>(std::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() && std::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 std::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);
}//===========================================================================
//
// Constructors
//
//===========================================================================String::String(const char *s)
{char *sl = const_cast<char*>(s);while (*sl)++sl;range_initializer(s, ++sl);
}//===========================================================================
//
// Big 5
//
//===========================================================================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()
{// \0 | -// ^ ^// elements first_free// last_elem capauto 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++, std::move(*elem++));free();elements = newdata;last_elem = dest - 1;first_free = dest;cap = elements + new_cap;
}void String::free()
{if (elements) {std::for_each(elements, first_free, [this](char &c){ alloc.destroy(&c); });alloc.deallocate(elements, cap - elements);}
}std::pair<char*, char*>
String::alloc_n_copy(const char *b, const char *e)
{auto str = alloc.allocate(e - b);return{ str, std::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, ' ');
}
#include "ex14_26_String.h"
#include <vector>
#include <iostream>
#include <algorithm>
#include <iterator>
#include <string>void foo(String x)
{std::cout << x << std::endl;
}void bar(const String& x)
{std::cout << x.c_str() << std::endl;
}String baz()
{String ret("world");return ret;
}int main()
{char text[] = "world";String s0;String s1("hello");String s2(std::move(s0));String s3 = s1;String s4(text);s2 = s1;if (s2 == s1)std::cout << "s2 == s1" << std::endl;foo(s1);bar(s1);foo("temporary");bar("temporary");String s5 = baz();std::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) {std::cout << s << std::endl;}std::cout << "Input a string: ";String s6;std::cin >> s6;std::cout << s6 << std::endl;if (s6 > s1)std::cout << "s6 > s1" << std::endl;std::cout << s5[2] << std::endl;
}
1.5 递减/递增运算符
*后置版本是通过调用前置版本来实现的,++this
前置版本**通常定义为类成员函数
返回递减/递增后对象的引用,保持与内置版本一致
前置与后置如何区分:后置版本接受一个额外的不被使用的int形参,(不会用到int,因此,不用命名,只起到标志的作用)
后置版本返回原值
前置版本实现:
inline StrBlobPtr& StrBlobPtr::operator++() //前置运算符
{ //如果curr已经指向了容器的尾后位置,则无法递增它check(curr, "increment past end of StrBlobPtr");++curr;//curr当前状态向前移动1个元素return *this;
}inline StrBlobPtr& StrBlobPtr::operator--() //前置运算符
{//如果curr已经指向了0位置,则无法递减它,将产生无效下标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;
}
由上可知后置版本是通过调用前置版本来实现的,
例如:后置递增运算符执行
++*this;
该表达式调用前置运算符,前置递增运算符首先检查递增操作是否安全,根据检查结果抛出异常或者执行递增curr的操作。假定通过了检查,后置递增返回事先存好的ret副本(递增前的值)。因此,表现效果为对象本身向前移动一个元素,而返回的结果仍然是未递增之前的值。
调用实例
StrBlobPtr p(a); //p指向a中的vector
p.operator++(0); //调用后置版本的operator++
p.operator++(); //调用前置版本的operator++
P14.27css
#include <vector>
using std::vector;#include <string>
using std::string;#include <initializer_list>
using std::initializer_list;#include <memory>
using std::make_shared; using std::shared_ptr;#include <exception>#ifndef _MSC_VER
#define NOEXCEPT noexcept
#else
#define NOEXCEPT
#endifclass 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(std::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(std::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 std::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) { }string& deref() const;StrBlobPtr& operator++();StrBlobPtr& operator--();StrBlobPtr operator++(int);StrBlobPtr operator--(int);StrBlobPtr& operator+=(size_t);StrBlobPtr& operator-=(size_t);StrBlobPtr operator+(size_t) const;StrBlobPtr operator-(size_t) const;string& operator[](size_t n);const string& operator[](size_t n) const;private:shared_ptr<vector<string>> check(size_t, const string&) const;std::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::operator++() //前置运算符
{ //如果curr已经指向了容器的尾后位置,则无法递增它check(curr, "increment past end of StrBlobPtr");++curr;return *this;
}inline StrBlobPtr& StrBlobPtr::operator--() //前置运算符
{//如果curr已经指向了0位置,则无法递减它,将产生无效下标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 std::runtime_error("unbound StrBlobPtr");if (i >= ret->size()) throw std::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& operator++();ConstStrBlobPtr& operator--();ConstStrBlobPtr operator++(int);ConstStrBlobPtr operator--(int);ConstStrBlobPtr& operator+=(size_t);ConstStrBlobPtr& operator-=(size_t);ConstStrBlobPtr operator+(size_t) const;ConstStrBlobPtr operator-(size_t) const;const string& operator[](size_t n) const;private:std::shared_ptr<vector<string>> check(size_t, const string&) const;std::weak_ptr<vector<string>> wptr;size_t curr;
};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&);inline const string& ConstStrBlobPtr::deref() const
{auto p = check(curr, "dereference past end");return (*p)[curr];
}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 std::shared_ptr<vector<string>> ConstStrBlobPtr::check(size_t i, const string &msg) const
{auto ret = wptr.lock();if (!ret) throw std::runtime_error("unbound StrBlobPtr");if (i >= ret->size()) throw std::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];
}
#include "ex14_27_28_StrBlob.h"
#include <algorithm>//==================================================================
//
// StrBlob - 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 std::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 !(rhs < lhs);
}bool operator>=(const StrBlob &lhs, const StrBlob &rhs)
{return !(lhs < rhs);
}//================================================================
//
// StrBlobPtr - operators
//
//================================================================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;
}//================================================================
//
// ConstStrBlobPtr - operators
//
//================================================================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 = std::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());
}
#include "ex14_27_28_StrBlob.h"
#include <iostream>int main()
{StrBlob sb1{ "a", "b", "c" };StrBlob sb2 = sb1;sb2[2] = "b";if (sb1 > sb2) {for (StrBlobPtr iter = sb1.begin(); iter < sb1.end(); ++iter)std::cout << iter.deref() << " ";std::cout << std::endl;}ConstStrBlobPtr iter(sb2);std::cout << (iter + 2).deref() << std::endl;
}
1.6 成员访问运算符
- 箭头运算符必须是类成员,解引用运算符通常是类成员
- 箭头运算符不像其他运算符可以任意指定其他操作,箭头运算符永远不能丢掉成员访问这个基本的定义。
- 形如
point->mem,point
必须是一个指向类对象的指针或者是一个重载了operstor->
的类对象,根据point类型不同point->mem
等价于
(*point).mem //point是一个内置类型指针
首先解引用该指针,然后从所得的对象获取指定的成员
point.operator->mem //point是一个类对像
P14.30 StrBlobPtr
inline const string& ConstStrBlobPtr::operator*() const
{auto p = check(curr, "dereference past end");return (*p)[curr]; //(*p)是对象的vector
}inline const string* ConstStrBlobPtr::operator->() const
{return &this->operator*();
}inline std::shared_ptr<vector<string>> ConstStrBlobPtr::check(size_t i, const string &msg) const
{auto ret = wptr.lock();if (!ret) throw std::runtime_error("unbound StrBlobPtr");if (i >= ret->size()) throw std::out_of_range(msg);return ret;
}
P14.31: StrBlobPtr
类没有定义复制构造函数、赋值操作符或析构函数。为什么可以呢?
应用3/5规则:没有需要处理的动态分配,因此合成析构函数就足够了。此外,不需要独特。因此,合成的可以处理所有相应的操作。
P14.32: 定义一个保存StrBlobPtr
指针的类,为该类定义重载的箭头操作符 。
#ifndef STRBLOBPTR_POINTER_H
#define STRBLOBPTR_POINTER_Hclass StrBlobPtr;/*** @brief a class that holds a pointer to a StrBlobPtr.*/
class StrBlobPtr_pointer
{
public:StrBlobPtr_pointer() = default;StrBlobPtr_pointer(StrBlobPtr* p) : pointer(p) { }StrBlobPtr& operator *() const;StrBlobPtr* operator->() const;private:StrBlobPtr* pointer = nullptr;
};
#include "ex14_32.h"
#include "ex14_30_StrBlob.h"
#include <iostream>StrBlobPtr&
StrBlobPtr_pointer::operator *() const
{return *pointer;
}StrBlobPtr*
StrBlobPtr_pointer::operator ->() const
{return pointer;
}int main()
{StrBlob sb{ "hello", "world" };StrBlobPtr iter = sb.begin();StrBlobPtr_pointer p(&iter);std::cout << p->deref() << std::endl;
}
1.7 函数调用运算符 operator()
仿函数 :通常与算法相结合,完成不同的策略的实现。Functor
- 如果类重载了函数调用运算符,就可以像使用函数一样使用该类的对象。则该类的对象称函数对象。
- 函数调用运算符必须是成员函数
如下实例:
for_each(a.begin(),a.end(),grater<int>());
struct absInt{int operator()(int val) const{return val<0 ? -val:val;}
};int i =-1;absInt absobj; //含有函数调用运算符的对象int ui=absInt(i); //将i传递给absobj。operator()
Exercise 14.33:
重载函数调用操作符可以接受多少操作运算对象?
Not really. Both can have at least 256 ones
It has been cleared discussed on Maximum number of parameters in function declaration.
**Exercise 14.35:**编写一个类似PrintString的类,从istream中读取一行输入,并返回表示所读取内容的字符串。如果读取失败,返回空字符串。
#include <iostream>
#include <string>class GetInput {
public:GetInput(std::istream &i = std::cin) : is(i) { }std::string operator()() const {std::string str;std::getline(is, str);return is ? str : std::string();}private:std::istream &is;
};int main()
{GetInput getInput;std::cout << getInput() << std::endl;
}
Exercise 14.36: 使用前面练习中的类读取标准输入,将每行作为vector中的元素存储
#include <iostream>
#include <string>
#include <vector>class GetInput {
public:GetInput(std::istream &i = std::cin) : is(i) { }std::string operator()() const {std::string str;std::getline(is, str);return is ? str : std::string();}private:std::istream &is;
};int main()
{GetInput getInput;std::vector<std::string> vec;for ( std::string tmp; !( tmp = getInput() ).empty(); ) vec.push_back( tmp );for (const auto &str : vec) std::cout << str << " ";std::cout << std::endl;
}
Exercise 14.37: 编写一个类来测试两个值是否相等。使用该对象和标准库算法编写一个程序来替换序列中给定值的所有实例。
#include <iostream>
#include <vector>
#include <algorithm>class IsEqual {int value;
public:IsEqual(int v) : value(v) { }bool operator()(int elem) {return elem == value;}
};int main()
{std::vector<int> vec = { 3, 2, 1, 4, 3, 7, 8, 6 };std::replace_if(vec.begin(), vec.end(), IsEqual(3), 5);for (int i : vec) std::cout << i << " ";std::cout << std::endl;
}
1.8 lambda是函数对象
- lambda表达式产生的类不含有默认构造函数,赋值运算符以及默认析构函数;它是否含有默认的拷贝/移动构造函数则通常取决于捕获的数据成员类型而定。
- 表示lambda及相应捕获行为的类:当lambda表达式通过引用捕获其变量时,由程序员确保引用对象确实存在。
Exercise 14.38: 编写一个类,用于测试给定字符串的长度是否与给定长度阈值匹配。使用该对象编写一个程序来报告输入文件中有多少单词的大小为1到10(含10)。
// Revise the previous program to report the count of words that are sizes
// 1 through 9 and 10 or more.
//#include <iostream>
#include <string>
#include <fstream>
#include <vector>
#include <map>struct IsInRange
{IsInRange(std::size_t lower, std::size_t upper):_lower(lower), _upper(upper){ }bool operator()(std::string const& str) const{return str.size() >= _lower && str.size() <= _upper;}std::size_t lower_limit() const{return _lower;}std::size_t upper_limit() const{return _upper;}
private:std::size_t _lower;std::size_t _upper;
};int main()
{//create predicates with various upper limits.std::size_t lower = 1;auto uppers = { 3u, 4u, 5u, 6u, 7u, 8u, 9u, 10u, 11u, 12u, 13u, 14u };std::vector<IsInRange> predicates;for (auto upper : uppers)predicates.push_back(IsInRange{ lower, upper });//create count_table to store counts std::map<std::size_t, std::size_t> count_table;for (auto upper : uppers)count_table[upper] = 0;//read file and countstd::ifstream fin("../data/storyDataFile.txt");for (std::string word; fin >> word; /* */)for (auto is_size_in_range : predicates)if (is_size_in_range(word))++count_table[is_size_in_range.upper_limit()];//printfor (auto pair : count_table)std::cout << "count in range [1, " << pair.first << "] : " << pair.second << std::endl;return 0;
}
Exercise 14.40: 重写10.3.2中的biggies函数,以使用函数对象类代替lambdas。
#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
using std::vector;
using std::string;
using std::cout; using std::endl;
using std::sort; using std::stable_sort; using std::for_each;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;
}int main()
{vector<string> vec{ "fox", "jumps", "over", "quick", "red", "red", "slow", "the", "turtle" };biggies(vec, 4);
}
Exercise 14.41: 为什么你认为新标准添加了lambdas?解释什么时候使用lambda,什么时候编写一个类。
lambda使用起来非常方便。
- 当functor不经常使用或不复杂时,Lambda可以被使用,
- 而functor应该比Lambda调用更多的次数,
- 或者作为Lambda实现起来相当复杂。
- 这个原因与lambda特点相同,详细参考
相关文章:
手动建库11.2.0.4
环境: oracle11.2.0.4 redhat6.2 在上篇文章中,我们只安装了oracle,还没有建立实例,本篇文章就来介绍如果手动建立实例。 1.创建密码文件(password file)----非必要 cd $ORACLE_HOME/dbs/ 查看是否有init.o…

滞后阈值边缘连接
// 边缘连接 void followEdges(int x, int y, Mat &magnitude, int tUpper,int tLower, Mat &edges) { edges.at<float>(y, x) 255; for (int i -1; i < 2; i) {for (int j -1; j < 2; j) {// 边界限制if((i ! 0) && (j ! 0) && (…

《复联4》的这波操作,其实是在灭 bug
前方涉及剧透,请谨慎阅读!!!前方涉及剧透,请谨慎阅读!!!前方涉及剧透,请谨慎阅读!!!↓↓↓Q1:您是否看了《复联4》?A、已看…

【C++】容器与继承
容器与继承 Exercise 15.28: Define a vector to hold Quote objects but put Bulk_quote objects into that vector. Compute the total net_price of all the elements in the vector. Exercise 15.29: Repeat your program, but this time store shared_ptrs to objects…

1.3 使用jmeter进行http接口测试
来源: http://www.cnblogs.com/alisapan/p/6150309.html 此篇纯是搬运记载。。 一、测试需求描述 1、 本次测试的接口为http服务端接口 2、 接口的主要分成两类,一类提供给查询功能接口,一类提供保存数据功能接口,这里我们举例2个…

opencv 自带库Canny边缘检测
#include "opencv2/imgproc/imgproc.hpp" #include "opencv2/highgui/highgui.hpp" int main( ) {// 读取源图像并转化为灰度图像cv::Mat srcImage cv::imread("..\\images\\flower.jpg",0);// 判断文件是否读入正确if( !srcImage.data ) retur…

git branch
git basic branch git branch <branchName>#create branch git branch --list#show branch list, git checkout <branchName>#choose branch,HEAD is pointer of the current branch last commit 复制代码create a file in branch 0.0.1,then checkout master ,mer…

读书笔记 effective c++ Item 5 了解c++默认生成并调用的函数
1 编译器会默认生成哪些函数 什么时候空类不再是一个空类?答案是用c处理的空类。如果你自己不声明,编译器会为你声明它们自己版本的拷贝构造函数,拷贝赋值运算符和析构函数,如果你一个构造函数都没有声明,编译器同样…

git tag学习记录(二)
文章目录1. git 工原理示意2. git tag记录2.1 git tag查看已有tag列表2.2 git tag标记当前分支上的 tag信息为-a v1.5.4 -m(给指定的commit打Tag)2.3 git push origin v1.5.4推送上一步打tag的分支到远程1. git 工原理示意 工作流程 TortoiseGit 2. g…

最小矩形与圆生成
#include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include <iostream> using namespace cv; using namespace std; int main() {cv::Mat img(500, 500, CV_8UC3);// 随机生成因子RNG& rng theRNG();for (;;){i…

详解微信域名防封的方法以及检测等工具的技术原理
微信域名完全防封是绝对不可能的,这是必须明确的,曾经有人打折《不死域名》的概念,它不是不死,是稍微命长一点,在推广上成本更低一下,效果更好一些,主要的技术原理是利用了腾讯云的域名安全联盟…

贝叶斯定理——数学之美
1.贝叶斯定理 1.1 定义:描述在已知一些条件下,某事件的发生概率 贝叶斯定理是关于随机事件A和B的条件概率的一则定理。 1.2 公式理解 P(x∣y)P(x)P(y∣x)P(y)P(x|y) \frac{ P(x)P(y|x)}{P(y)}P(x∣y)P(y)P(x)P(y∣x) 其中x以及y为随机事件ÿ…

HUST 1586 数字排列
1586 - 数字排列 时间限制:1秒 内存限制:128兆 91 次提交 36 次通过 题目描述现有n个k位的数字,你的任务是重新安排数字每一位的位置,使得重新安排后这n个数字中最大的数字和最小的数字之差的绝对值最小,对于每一位的调…

最小矩形与圆生成1
#include <opencv2/imgproc/imgproc.hpp> #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <iostream> #include <stdio.h> using namespace cv; using namespace std; // 计算外接矩形与圆轮廓…

kettle-核心概念
转载于:https://www.cnblogs.com/LXL616/p/10836183.html

adb调试命令小结
adb调试命令 adb 连接android设备 adb connect 192.168.103.246 connected to 192.168.103.246:5555 sunsun:~/workspace/deptrum$ adb connect 192.168.103.246:5555 already connected to 192.168.103.246:5555 sunsun:~/workspace/deptrum$ adb shell tb8788p1_64_bsp_wxp…

github创建本地库后关联远程库
在进行新项目开发时,有时候并不一定先创建远程库,而是先在本地将项目创建,到一定阶段后再与远程库关联。下面步骤解决本地库与远程库在这种情形。 1. 初始化本地库,既然项目已经创建了,相信这个也已经知道了。 git ini…

mysql以及mysql bench安装教程
首先,我们需要去官网下载mysql(这里以下载) 1 2 3 4 5 下载好了自己好了之后,点击安装好的东西出现如下界面: 1、接受使用条款并点击next 2、点击custom,可以根据个人习惯进行安装 3、这里来是需要安装的一…

【NEON 】初探
NEON 文章目录NEON1 neon窥探1.1 neon用途1.2 neon处理机制1.3 neon发展历程中的优缺点对比1.4 为什么使用neon1.5 Armv7/v8详细差异1.6 Register寄存器1.7 指令系统间的关系与1.3相似2 neon 使用2.1 neon 指令格式2.2 AArch64 NEON 指令语法2.3 NEON 指令3.1 RK3399资料1 neon…

sql 常用 语法
2019独角兽企业重金招聘Python工程师标准>>> 1. 字段 不重复 ALTER TABLE sys_workday ADD UNIQUE (ymd) ; 转载于:https://my.oschina.net/u/1760858/blog/838385

moravec 角点检测
#include <opencv2/opencv.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> using namespace std; using namespace cv; // MoravecCorners角点检测 cv::Mat MoravecCorners(cv::Mat srcImage, int kSize, int thresho…

js控制视频播放
2019独角兽企业重金招聘Python工程师标准>>> 1、js控制视频播放 1、页面html <div id"slide" class"videoWrap"></div><canvas v-show"!isShowVideoCover" id"canvas" class"videoCanvas"><…

valgrind-yyds——memcheck检查程序中的内存问题,如泄漏、越界、非法指针等。
Valgrind 用户手册 文章目录1. valgrind概述2. Valgrind 原理及安装2.1 [Valgrind 做了什么](https://www.valgrind.org/docs/manual/manual-core.html)2.2 安装3 内存检测3.1 memcheck 常用检测指令3 .2 内存检测结果3 .3 内存检测含义3 .4 内存检测更多例子1. valgrind概述 …

数据传送到后端(二)
先在myeclipse里建立上图文件,然后在TestServlet.java里面的doGet{}括号里面填入以下内容: public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //解决中文乱码 request.setCharacte…

HSV 通道分离
// 转换成hsv cv::Mat img_h, img_s, img_v, imghsv;std::vector<cv::Mat> hsv_vec;cv::cvtColor(srcImage, imghsv, CV_BGR2HSV);cv::imshow("hsv", imghsv);cv::waitKey(0);// 分割hsv通道cv::split(imghsv, hsv_vec);img_h hsv_vec[0];img_s hsv_vec[1];i…

阿里云安全肖力:安全基础建设是企业数字化转型的基石
2019独角兽企业重金招聘Python工程师标准>>> 企业在享受数字化转型带来利好的同时,其面临的安全问题也愈发复杂。一方面,外部威胁不断升级,近期利用海量移动设备发起DDoS攻击的案例表明,黑灰产作案手法也在随着时代的发…

Shell 函数、数组与正则表达式
防伪码:白日依山尽,黄河入海流。5.1 函数格式:func() {command}示例 1:#!/bin/bashfunc() {echo "This is a function."}func# bash test.shThis is a function.Shell 函数很简单,函数名后跟双括号…

valgrind——Cachegrind分析CPU的cache命中率、丢失率,用于进行代码优化。
功能扩展1 Cachegrind 1.1 指令范式 单行最重要指令: valgrind --tool [default: memcheck] sunsun:~/workspace/deptrum$ valgrind --tool //table 查看工具 cachegrind callgrind drd exp-bbv exp-dhat exp-sgcheck getoff he…

细化 Sobel 边缘提取
bool SobelVerEdge(cv::Mat srcImage, cv::Mat& resultImage) {CV_Assert(srcImage.channels() 1);srcImage.convertTo(srcImage, CV_32FC1);// 水平方向的 Sobel 算子cv::Mat sobelx (cv::Mat_<float>(3, 3) << -0.125, 0, 0.125,-0.25, 0, 0.25,-0.125, 0,…

PRD 的编写和修改注意事项
2019独角兽企业重金招聘Python工程师标准>>> 每个操作的发生时机(状态)要搞清楚,表达逻辑时一定要用准确的词语,避免对自己和别人造成误会。状态图,标识状态的流转和事件发生点评审PRD时最好记录下修改的内…