第四讲 STL相关的内容
Hash Function
- 将hash函数封装成类对象
- hash_val进行拆解传入参数,进行循环
- 每次拆解一个参数,都需要更新种子
- TR1的工具,)0x9e3779b9是黄金比例数字0.618
- 测试
- 当没有指定hash函数时,用默认的hash
函数,但是针对特殊的类型,有自己特化的hash 函数 ![](http://i.imgur.com/KY0LFM5.png)
tuple用例
- 测试
- 实现,递归的继承实现自动添加任意多个函数,需要有终止条件无参数偏特化版本
- 元组大小决定由类的继承关系决定
type traits
- 测试,traits回答type的类型
- 区别拷贝和‘搬运’构造函数
cout
- cout继承关系,把已有的类型放入cout才可以输出
moveable
- 深浅拷贝
- 使用move后,保证原来的地址不在使用
- 测试 ```C using namespace std; const long ASIZE = 500000L;
//—————————————————-
#include
//以下 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)
}
++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;
}
if (_data) {
delete _data;
}
}
{
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
//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
}
++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;
if (_data) {
delete _data;
}
}
return string(this->_data) < string(rhs._data); //借用事實:string 已能比較大小.
}
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
//—————————————————-
#include
#include
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
//測試 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; } ```