目录
一个万用的hash_function
将hash函数封装成类对象
- hash_val进行拆解传入参数,进行循环
- 每次拆解一个参数,都需要更新种子
- TR1的工具,)0x9e3779b9是黄金比例数字0.618
测试
当没有指定hash函数时,用默认的hash函数,但是针对特殊的类型,有自己特化的hash函数
Tuple用例
测试
- 实现,递归的继承实现自动添加任意多个函数,需要有终止条件无参数偏特化版本
- 元组大小决定由类的继承关系决定
type traits
测试,traits回答type的类型
区别拷贝和‘搬运’构造函数
cout
cout继承关系,把已有的类型放入cout才可以输出
movable元素对于deque速度现的影响
- 深浅拷贝
- 使用move后,保证原来的地址不在使用
测试函数
using namespace std; const long ASIZE = 500000L; //---------------------------------------------------- #include <iostream> #include <cstdio> //snprintf() #include <cstdlib> //RAND_MAX #include <cstring> //strlen(), memcpy() #include <string> using std::cin; using std::cout; using std::string; //以下 MyString 是為了測試 containers with moveable elements 效果. class MyString { public: static size_t DCtor; //累計 default-ctor 的呼叫次數 static size_t Ctor; //累計 ctor 的呼叫次數 static size_t CCtor; //累計 copy-ctor 的呼叫次數 static size_t CAsgn; //累計 copy-asgn 的呼叫次數 static size_t MCtor; //累計 move-ctor 的呼叫次數 static size_t MAsgn; //累計 move-asgn 的呼叫次數 static size_t Dtor; //累計 dtor 的呼叫次數 private: char* _data; size_t _len; void _init_data(const char *s) { _data = new char[_len+1]; memcpy(_data, s, _len); _data[_len] = '\0'; } public: //default ctor MyString() : _data(NULL), _len(0) { ++DCtor; } //ctor MyString(const char* p) : _len(strlen(p)) { ++Ctor; _init_data(p); } // copy ctor MyString(const MyString& str) : _len(str._len) { ++CCtor; _init_data(str._data); //COPY } //move ctor, with "noexcept" MyString(MyString&& str) noexcept : _data(str._data), _len(str._len) { ++MCtor; str._len = 0; str._data = NULL; //避免 delete (in dtor) } //copy assignment MyString& operator=(const MyString& str) { ++CAsgn; if (this != &str) { if (_data) delete _data; _len = str._len; _init_data(str._data); //COPY! } else { // Self Assignment, Nothing to do. } return *this; } //move assignment MyString& operator=(MyString&& str) noexcept { ++MAsgn; if (this != &str) { if (_data) delete _data; _len = str._len; _data = str._data; //MOVE! str._len = 0; str._data = NULL; //避免 deleted in dtor } return *this; } //dtor virtual ~MyString() { ++Dtor; if (_data) { delete _data; } } bool operator<(const MyString& rhs) const //為了讓 set較大小 { return std::string(this->_data) < std::string(rhs._data); //借用事實:string 已能比較大小. } bool operator==(const MyString& rhs) const //為了讓 set 判斷相等. { return std::string(this->_data) == std::string(rhs._data); //借用事實:string 已能判斷相等. } char* get() const { return _data; } }; size_t MyString::DCtor=0; size_t MyString::Ctor=0; size_t MyString::CCtor=0; size_t MyString::CAsgn=0; size_t MyString::MCtor=0; size_t MyString::MAsgn=0; size_t MyString::Dtor=0; namespace std //必須放在 std 內 { template<> struct hash<MyString> //這是為了 unordered containers { size_t operator()(const MyString& s) const noexcept { return hash<string>()(string(s.get())); } //借用現有的 hash<string> (in ...\include\c++\bits\basic_string.h) }; } //----------------- //以下 MyStrNoMove 是為了測試 containers with no-moveable elements 效果. class MyStrNoMove { public: static size_t DCtor; //累計 default-ctor 的呼叫次數 static size_t Ctor; //累計 ctor 的呼叫次數 static size_t CCtor; //累計 copy-ctor 的呼叫次數 static size_t CAsgn; //累計 copy-asgn 的呼叫次數 static size_t MCtor; //累計 move-ctor 的呼叫次數 static size_t MAsgn; //累計 move-asgn 的呼叫次數 static size_t Dtor; //累計 dtor 的呼叫次數 private: char* _data; size_t _len; void _init_data(const char *s) { _data = new char[_len+1]; memcpy(_data, s, _len); _data[_len] = '\0'; } public: //default ctor MyStrNoMove() : _data(NULL), _len(0) { ++DCtor; _init_data("jjhou"); } //ctor MyStrNoMove(const char* p) : _len(strlen(p)) { ++Ctor; _init_data(p); } // copy ctor MyStrNoMove(const MyStrNoMove& str) : _len(str._len) { ++CCtor; _init_data(str._data); //COPY } //copy assignment MyStrNoMove& operator=(const MyStrNoMove& str) { ++CAsgn; if (this != &str) { if (_data) delete _data; _len = str._len; _init_data(str._data); //COPY! } else { // Self Assignment, Nothing to do. } return *this; } //dtor virtual ~MyStrNoMove() { ++Dtor; if (_data) { delete _data; } } bool operator<(const MyStrNoMove& rhs) const //為了讓 set 比較大小 { return string(this->_data) < string(rhs._data); //借用事實:string 已能比較大小. } bool operator==(const MyStrNoMove& rhs) const //為了讓 set 判斷相等. { return string(this->_data) == string(rhs._data); //借用事實:string 已能判斷相等. } char* get() const { return _data; } }; size_t MyStrNoMove::DCtor=0; size_t MyStrNoMove::Ctor=0; size_t MyStrNoMove::CCtor=0; size_t MyStrNoMove::CAsgn=0; size_t MyStrNoMove::MCtor=0; size_t MyStrNoMove::MAsgn=0; size_t MyStrNoMove::Dtor=0; namespace std //必須放在 std 內 { template<> struct hash<MyStrNoMove> //這是為了 unordered containers { size_t operator()(const MyStrNoMove& s) const noexcept { return hash<string>()(string(s.get())); } //借用現有的 hash<string> (in ...\4.9.2\include\c++\bits\basic_string.h) }; } //---------------------------------------------------- #include <iostream> #include <cstdio> //snprintf() #include <cstdlib> //RAND_MAX #include <string> #include <algorithm> #include <list> #include <forward_list> using std::cin; using std::cout; using std::string; using std::max; using std::min; namespace jj00 { bool strLonger(const string& s1, const string& s2) { return s1.size() < s2.size(); } void test_misc() { cout << "\ntest_misc().......... \n"; //以下這些是標準庫的眾多容器的 max_size() 計算方式. cout << size_t(-1) << endl; //4294967295 cout << size_t(-1)/sizeof(long) << endl; //1073741823 cout << size_t(-1)/sizeof(string) << endl; //1073741823 cout << size_t(-1)/sizeof(_List_node<string>) << endl; //357913941 cout << size_t(-1)/sizeof(_Fwd_list_node<string>) << endl; //536870911 cout << "RAND_MAX= " << RAND_MAX << endl; //32767 cout << min( {2,5,8,9,45,0,81} ) << endl; //0 cout << max( {2,5,8,9,45,0,81} ) << endl; //81 vector<int> v {2,5,8,9,45,0,81}; cout << "max of zoo and hello : " << max(string("zoo"), string("hello")) << endl; //zoo cout << "longest of zoo and hello : " << max(string("zoo"), string("hello"), strLonger) << endl; //hello cout << hash<MyString>()(MyString("Ace")) << endl; //1765813650 cout << hash<MyString>()(MyString("Stacy")) << endl; //2790324277 cout << "MyString(zoo) < MyString(hello) ==> " << (MyString("zoo") < MyString("hello")) << endl; //0 cout << "MyString(zoo) == MyString(hello) ==> " << (MyString("zoo") == MyString("hello")) << endl; //0 cout << "MyStrNoMove(zoo) < MyStrNoMove(hello) ==> " << (MyStrNoMove("zoo") < MyStrNoMove("hello")) << endl; //0 cout << "MyStrNoMove(zoo) == MyStrNoMove(hello) ==> " << (MyStrNoMove("zoo") == MyStrNoMove("hello")) << endl; //0 //以上建構了 6 個 MyString objects 和 4 個 MyStrNoMove objects,都是暫時生命. } } //-------------------------------------------------- #include <typeinfo> //typeid() template<typename T> void output_static_data(const T& myStr) { cout << typeid(myStr).name() << " -- " << endl; cout << " CCtor=" << T::CCtor << " MCtor=" << T::MCtor << " CAsgn=" << T::CAsgn << " MAsgn=" << T::MAsgn << " Dtor=" << T::Dtor << " Ctor=" << T::Ctor << " DCtor=" << T::DCtor << endl; } #include <ctime> //clock_t, clock() template<typename M, typename NM> void test_moveable(M c1, NM c2, long& value) { char buf[10]; //測試 move cout << "\n\ntest, with moveable elements" << endl; typedef typename iterator_traits<typename M::iterator>::value_type V1type; clock_t timeStart = clock(); for(long i=0; i< value; ++i) { snprintf(buf, 10, "%d", rand()); auto ite = c1.end(); c1.insert(ite, V1type(buf)); } cout << "construction, milli-seconds : " << (clock()-timeStart) << endl; cout << "size()= " << c1.size() << endl; output_static_data(*(c1.begin())); timeStart = clock(); M c11(c1); cout << "copy, milli-seconds : " << (clock()-timeStart) << endl; timeStart = clock(); M c12(std::move(c1)); cout << "move copy, milli-seconds : " << (clock()-timeStart) << endl; timeStart = clock(); c11.swap(c12); cout << "swap, milli-seconds : " << (clock()-timeStart) << endl; //測試 non-moveable cout << "\n\ntest, with non-moveable elements" << endl; typedef typename iterator_traits<typename NM::iterator>::value_type V2type; timeStart = clock(); for(long i=0; i< value; ++i) { snprintf(buf, 10, "%d", rand()); auto ite = c2.end(); c2.insert(ite, V2type(buf)); } cout << "construction, milli-seconds : " << (clock()-timeStart) << endl; cout << "size()= " << c2.size() << endl; output_static_data(*(c2.begin())); timeStart = clock(); NM c21(c2); cout << "copy, milli-seconds : " << (clock()-timeStart) << endl; timeStart = clock(); NM c22(std::move(c2)); cout << "move copy, milli-seconds : " << (clock()-timeStart) << endl; timeStart = clock(); c21.swap(c22); cout << "swap, milli-seconds : " << (clock()-timeStart) << endl; }