static變量在不同的對(duì)象
#include<iostream>
using namespace std;
template <typename T>
class Test{
public:
static int _data;
int a;
};
template<>int Test<int>::_data = 1;
template<>int Test<char>::_data = 2;
//static變量是屬于整個(gè)類(lèi),而不是某個(gè)對(duì)象
int main()
{
cout<<Test<int>::_data<<endl;//1
cout<<Test<char>::_data<<endl;//2
Test<int> obji1,obji2;
Test<char> objc1,objc2;
cout<<obji1._data<<endl;//1
cout<<obji2._data<<endl;//1
cout<<objc1._data<<endl;//2
cout<<objc2._data<<endl;//2
obji1._data = 3;//_data = 3共同屬于obji1和obji2對(duì)象
objc2._data = 4;
cout<<obji1._data<<endl;//3
cout<<obji2._data<<endl;//3
cout<<objc1._data<<endl;//4
cout<<objc2._data<<endl;//4
obji1.a = 222;//a = 222是屬于obji1這個(gè)對(duì)象的,不屬于obji2對(duì)象
cout<<obji1.a<<endl;//222
cout<<obji2.a<<endl;//隨機(jī)
}
STL中的迭代器
template<class T>
class List{
public:
void insert_front(T value);
void insert_end(T value);
void display() const();
ListItem<T>* begin() const
{
return _front;
}
typedef ListIter<ListItem<T>> iterator;//所以說(shuō)迭代器是一個(gè)對(duì)象,是一個(gè)行為類(lèi)似指針的對(duì)象。和智能指針一樣,是個(gè)對(duì)象。
private:
ListItem<T>* _end;
ListItem<T>* _front;
long _size;
};
template<class T>
class ListItem{
public:
T value() const
{
return _value;
}
ListItem* next() const
{
return _next;
}
private:
T _value;
ListItem<T>* _next;
};
template<class Item>
struct ListIter
{
Item* ptr;
ListIter(Item* p = NULL):ptr(p){}
Item& operator *() const
{
return *ptr;
}
Item* operator ->() const
{
return ptr;
}
ListIter& operator ++()
{
ptr = ptr->next();
return *this;
}
ListIter& operator ++(int)
{
ListIter tmp = *this;
++(*this);
return temp;
}
bool operator ==(const ListIter &i) const
{
return ptr == i.ptr;
}
bool operator !=(const ListIter &i) const
{
return ptr != i.ptr;
}
};
void main()
{
List<int> myList;
for(int i = 0;i < 5;++i)
{
myList.insert_front(i);
myList.insert_end(i+2);
}
list<int>::iterator pd;
pd = myList.begin();
}
類(lèi)模板中可以再有一個(gè)模板函數(shù)(class template中可以再有template(menbers))
#include<iostream>
using namespace std;
class alloc{
};
//迭代器的定義方法,其實(shí)迭代器是一個(gè)T類(lèi)型的指針 vector<int>::iterator pd. pd就是一個(gè)int類(lèi)型的指針。
template<class T,class Alloc = alloc>
class vector{
public:
typedef T value_type;
typedef value_type* iterator;
template<class I>
void insert(iterator position,I first,I last)
{
cout<<"insert()"<<endl;
}
};
int main()
{
int ia[5] = {0,1,2,3,4};
vector<int> x;
vector<int>::iterator ite;
x.insert(ite,ia,ia+5);
}
template參數(shù)可以根據(jù)前一個(gè)template參數(shù)設(shè)定默認(rèn)值
#include<iostream>
using namespace std;
class alloc{
};
template<class T,class Alloc = alloc,size_t BufSiz = 0>
class deque{
public:
deque(){cout<<"deque"<<endl;}
};
template<class T,class Sequence = deque<T>>//相當(dāng)于template<class T,class Sequence = deque<T,alloc,0>>
class stack{
public:
stack(){cout<<"stack"<<endl;}
private:
Sequence c;
};
int main()
{
stack<int> x;//輸出 deque和stack
}
臨時(shí)對(duì)象的產(chǎn)生于運(yùn)用
template<class T>
class print{
public:
void operator()(const T &elem)//注意若是重載運(yùn)算符(),函數(shù)定義為 print operator()(const T &elem)
{
cout<<elem<<' ';
}
};
template<class T>
static void out(T n)
{
cout<<n<<" ";
}
int main()
{
int ia[6] = {0,1,2,3,4,5};
vector<int> iv(ia,ia+6);
//print<int>(iv.begin());//調(diào)用失敗
for_each(iv.begin(),iv.end(),print<int>());//print<int>()是一個(gè)臨時(shí)對(duì)象,不是一個(gè)函數(shù)調(diào)用操作
for_each(iv.begin(),iv.end(),out<int>);//平時(shí)都是使用這種方式調(diào)用。
}
STL空間配置器
在程序設(shè)計(jì)中,我們不免因?yàn)槌绦蛐枨螅褂煤芏嗟男K內(nèi)存(基本類(lèi)型以及小內(nèi)存的自定義類(lèi)型)。在程序中動(dòng)態(tài)申請(qǐng),釋放。這個(gè)過(guò)程過(guò)程并不是一定能夠控制好的,于是乎,
問(wèn)題1:就出現(xiàn)了內(nèi)存碎片問(wèn)題。(ps外碎片問(wèn)題)
問(wèn)題2:一直在因?yàn)樾K內(nèi)存而進(jìn)行內(nèi)存申請(qǐng),調(diào)用malloc,系統(tǒng)調(diào)用產(chǎn)生性能問(wèn)題。
注:內(nèi)碎片:因?yàn)閮?nèi)存對(duì)齊/訪問(wèn)效率(CPU取址次數(shù))而產(chǎn)生 如 用戶需要3字節(jié),實(shí)際得到4或者8字節(jié)的問(wèn)題,其中的碎片是浪費(fèi)掉的。
外碎片:系統(tǒng)中內(nèi)存總量足夠,但是不連續(xù),所以無(wú)法分配給用戶使用而產(chǎn)生的浪費(fèi)。
這兩個(gè)問(wèn)題解釋清楚之后,就來(lái)談STL空間配置器的實(shí)現(xiàn)細(xì)節(jié)了
實(shí)現(xiàn)策略
用戶申請(qǐng)空間大于128B?
yes:調(diào)用一級(jí)空間配置器
no:調(diào)用二級(jí)空間配置器
大致實(shí)現(xiàn)為:
二級(jí)空間配置由內(nèi)存池以及伙伴系統(tǒng):自由鏈表組成
一級(jí)空間配置器直接封裝malloc,free進(jìn)行處理,增加了C++中的set_handler機(jī)制(這里其實(shí)也就是個(gè)略顯牽強(qiáng)的裝飾/適配模式了),增加內(nèi)存分配時(shí)客戶端可選處理機(jī)制。
void MyOutOfMemory()
{
cout << "Out of memory error!" << endl;
abort();
}
int main()
{
set_new_handler(MyOutOfMemory);
int *verybigmemory = new int[0x1fffffff];//不能正常分配內(nèi)存的時(shí)候,調(diào)用MyOutOfMemory函數(shù)
delete verybigmemory;
}
可配置性:
客戶端可以通過(guò)宏__USE_MALLOC進(jìn)行自定義選擇是否使用二級(jí)空間配置器。
一級(jí)空間配置器就主要封裝malloc,添加handler機(jī)制了,這里就不羅嗦了,相信各位都是可以通過(guò)源碼了解到的
[圖片上傳失敗...(image-8506b-1560669207937)]

偏特化和萃取
template<class T>
struct iterator_traites{
typedef T value_type;
};
template<class T>
struct iterator_traites<T *>{
typedef T value_type;
};
template<class T>
struct iterator_traites<const T *>{
typedef T value_type;
};
template<class T>
struct TraitsHelper{//注意這是一個(gè)普通的類(lèi)模板
static const bool isPointer = false;
};
template<class T>
struct TraitsHelper<T*>{
static const bool isPointer = true;
};
template <typename T>
class Test {
public:
typedef typename iterator_traites<T>::value_type iv;
iv Compute()
{
if(TraitsHelper<T>::isPointer)
cout<<"is pointer"<<endl;
else
cout<<"not pointer"<<endl;
iv k;//如果傳進(jìn)來(lái)的是指針,那么k就是一個(gè)指針,如果傳進(jìn)來(lái)的是普通類(lèi)型,那么k就是普通類(lèi)型。
return k;
}
private:
T mData;
};
int main()
{
Test<int *> t1;
cout<<t1.Compute()<<endl;
}
STL中的配接器adapter
配接器(適配器)也是一種設(shè)計(jì)模式,在C++1中和單例模式都有介紹,是對(duì)某種方法的再封裝改造。官方解釋為:將一個(gè) class 的接口轉(zhuǎn)換為另一個(gè) class 的接口,使原本因接口不兼容而不能合作的 classes,可以一起運(yùn)作。一言以蔽之,Adapter 用于改變接口。
STL提供了三種適配器:
1.改變?nèi)萜鹘涌?,稱(chēng)之為container adapter
2.改變迭代器接口,稱(chēng)之為iterator adapter
3.改變仿函數(shù)接口,稱(chēng)之為function adapter
應(yīng)用于容器:queue和stack嚴(yán)格意義上來(lái)說(shuō)是配接器而不是容器,因?yàn)閝ueue和stack是對(duì)deque的再封裝(接口的改造)。
set和map(序列式容器)是對(duì)紅黑樹(shù)的再封裝(接口的改造)。
應(yīng)用于迭代器:
(1)insert iterators(2)reverse iterators(3)iostream iterators istream_iterator ostream_iterator
所謂 insert iterators,可以將一般迭代器的賦值(=,assign)操作變?yōu)椴迦耄╥nsert)操作。這樣的迭代器包括專(zhuān)司尾端插入操作back_insert_iterator,專(zhuān)司頭端插入的 front_insert_iterator,以及可在任意位置執(zhí)行插入操作的 insert_iterator。由于這三個(gè) iterator adapters 的使用接口不太直觀,給一般用戶帶來(lái)困擾,STL 提供三個(gè)相應(yīng)函數(shù),back_inserter_iterator()、front_inserter_iterator()、inserter_iterator()
template <typename Container>
class BackInsertIterator
{
public:
typedef typename Container::value_type value_type;
explicit BackInsertIterator(Container &cont)//類(lèi)屬性是一個(gè)容器,這個(gè)類(lèi)就是對(duì)這個(gè)容器操作
:_cont(cont)
{ }
BackInsertIterator<Container> &operator= (const value_type &val)
{
_cont.insert(_cont.end(), val);//其實(shí)還是調(diào)用了容器的插入操作(再封裝)
return *this;
}
BackInsertIterator<Container> &operator*()
{ return *this; }
BackInsertIterator<Container> &operator++()
{ return *this; }
BackInsertIterator<Container> &operator++(int)
{ return *this; }
private:
Container &_cont;
};
在使用的時(shí)候:
int main()
{
char a[6]={'a','b','c','d','f','g'};
vector <char> b(6);
b.push_back('k');b.push_back('m');
copy(a,a+4,back_insert_iterator< vector<char> >(b));
for(int i = 0;i < b.size();++i)
cout<<b[i]<<" ";
return 0;
}
應(yīng)用于仿函數(shù):
functor adapters(亦稱(chēng)為 function adapters)是所有配接器中數(shù)量最為龐大的一個(gè)族群,其配接靈活程度也非前二者所能及,可以配接、配接、再配接。這些配接操作包括,
(1)系結(jié)(bind)、否定(negate)、組合(compose),
(2)以及對(duì)一般函數(shù)或成員函數(shù)的修飾(使其成為一個(gè)仿函數(shù))