Standard Template Library
2017年8月17日
9:30
推薦閱讀
Algorithms + Data Structures
= Programs
1976 wirtten by
Niklasu Wirth
Pascal語言之父
·C++基本語法
·模版(template)基礎
-事半功倍
·數據結構(data structures)和算法(algorithms)概念
-如魚得水
三
想
GNU-C V2.9.1 && V4.9
標準庫版本,Visual C++
源代碼分布:
file layout
VS2013
…\include子目錄
Dec+C++ 5.1.1 with GNU V4.9.2
…\include\c++內并非實做內容
…\include\c++\ext
blabla allocator
OOP (Object-oriented programming)vs. GP(Generic Programming)
2017年8月21日
11:27
查看大型OOP庫的難點
繼承關系復雜、
虛函數
OOP 企圖將datas和methods關聯在一起
?
template<class T,
??? calss Alloc = alloc>
class list{
…
void sort();
};
標準庫沒有這種困擾
list不能使用::sort()的原因
?
*first + *(last - first)/2
只有RandomAccessIterator
才能如此操作
而list的iterator并不是這種類型
所以,不能使用
GP將datas和methods分開來
?
采用GP:
·Containers和Algorithms團隊可以各自
閉門造車,其間以Iterator溝通即可
·Algorithms通過Iterators確定操作范圍
,并通過Iterators取用Container元素
所有algorithms,其內最終
涉及元素本身的操作,無非
就是比大小
閱讀C++標準庫源碼的必要基礎
2017年8月21日
11:50
·Operator Overloading
迭代器重載
?
·Templates
-Class Templates,類模板
-Function Templates,函數模板
實參推導
-Member Templates,成員模板
Specialization,特化
template<>
struct __type_traits<int>
{
…
};
__type_traits<Foo>::has_trivial_destructor
template<> || __STL_TEMPLATE_NULL
Partial Specialization,偏特化
偏:1.數量上的偏 2.范圍上的偏
推薦閱讀
C++ Templates
再談分配器
不建議直接使用分配器
2017年8月21日
12:51
malloc
VC6附加標準庫的allocator
分配器 調用 operator new
operator new 調用malloc
VC6 & BC++ & GCC2.9
的allocator只是以
::operator new和
::operator delete完成
allocate()和dellocate()
沒有任何特殊設計
malloc附帶額外開銷
allocator
區塊小 開銷比例大 -->難以接受
區塊大 開銷比例小
GNU-C 2.9比較好 GNU-C 4.9又回到了VC BC的模式
GNU-C 2.9版本的alloc還在 在G4.9中改名為__pool_alloc
G2.9 alloc 容器模式下 不帶cookie 額外開銷
?
容器之間的實現關系與分類
2017年8月21日
14:55
容器,結構與分類
?
容器list
2017年8月21日
15:03
一大堆typedef
node->link_type->list_node*
?
sizeof(list)應該是4
?
template<class T>
struct __list_node
{
typedef void* void_pointer;
void_pointer pre;
void_pointer next;
T data;
}
所有的容器必然有一個typedef? blablabla iterator
所有iterator都必須typedef五個類型
?一大組的操作符重載
list's iterator
list<Foo>::iterator it;
postfix form ++
前++ 返回reference
后++ 返回非reference 禁止連續++
?
像偶像(int)致敬
?
->和* 提取值
*返回T&
->返回T*
容器list
2017年8月22日
15:08
G2.9
一堆typedef + 一堆操作符重載
G4.9相較于G2.9:
·模板參數只有一個(易理解)
·node結構有其parent
·node的成員type較精確
G4.9
迭代器設計原則
2017年8月22日
15:23
traits : 特征、特性、特質
人為設置的一種萃取機制
iterator需要遵循的原則
算法和容器之間的橋梁
?
iterator_category
difference_type
value_type
reference
pointer
iterator associated type
iterator traits
type traits
character traits
pointer traits
算法rotate 調用std::__rotate()
?
std::__rotate(…, std::__iterator_category(__first));
iterator traits誕生的因由:
iterator并不是一個class而是native pointer的時候
無法回答這五個問題
(native pointer 被視為一種退化的iterator)
迭代器設計原則
2017年8月22日
15:42
銀彈
判斷扔進去的是否為class形式的iterator
如果是 則采用問答方式得出
如果不是 偏特化 typedef? 代其回答
容器vector
2017年8月22日
15:57
template<class T, class Alloc = alloc>
class vector
{
public:
typedef T????????????????????? value_type;
typedef value_type*? iterator;
typedef value_type& reference;
typedef size_t???????????? size_type;
protected:
iterator start;
iterator finish;
iterator end_of_storage;
public:
iterator begin() { return start;}
iterator end() {return finish;}
size_type size() const {return size_type(end() - begin());}
…
};
NOTICE:大量調用拷貝構造和析構
vector's iterator
public繼承
是一種
is-a關系
array和forwardlist
2017年8月22日
16:34
容器array
單向鏈表只能++ 往一個方向走
關于作業
2017年8月25日
11:08
創建一個list容器,放置6個整型數值[0, 1, 30, 20, 10, 0]
1.?從后向前打印出容器內的元素
2.?向list容器后面添加兩個元素,并對容器內的值求和并打印
3.?打印鏈表的中間元素
4.?找到不為0的元素,復制到一個vector中并打印vector元素
來自 <http://mooc.study.163.com/learn/GeekBand-2001184001?tid=2001361008#/learn/hw?id=2001591031&r=true>
創建一個list容器 放置整形值
list<int> i_list
以一個數組進行容器的初始化
所以需要先聲明并給這個數組賦值
int src_int[6] = {0, 1, 30, 20, 10, 0};
list的構造函數允許將兩個其他容器的迭代器
作為參數傳入進行list的構造
list<int> i_list(&src_int[0], &src_int[6]);???????? //創建list容器,并將6個數值放入
?
?
1.從后向前打印出容器內的元素
list自身攜帶逆序迭代器,想要從后向前打印list內
元素,則采用逆序迭代器遍歷輸出即可
?
for (auto it = i_list.rbegin(); it != i_list.rend(); ++it) //采用逆序迭代器從后向前打印出容器內的元素
{
cout << *it << " ";
}
cout << "\r\n打印完畢" << endl;
2.向list容器后面添加兩個元素并對容器內的值求和并打印
先使用cin獲得需要添加的兩個元素
調用push_back()將這兩個元素添加到list的末尾
初始化和sum為0
采用迭代器遍歷整個容器,將所有值疊加至sum即為所有元素的和
int a, b;
cout << "請輸入需要添加的元素的值:" << endl;
cin >> a >> b;
i_list.push_back(a);
i_list.push_back(b);
int sum = 0;
for (auto it = i_list.begin(); it != i_list.end(); ++it)
{
sum += (*it);
}
?
關于作業
2017年8月25日
11:15
3.打印鏈表的中間元素
?
考慮到鏈表的長度(size)可能為奇數也可能為偶數
?
當長度為奇數時 正中間的元素即為中間元素
當長度為偶數時 中間的兩個元素均為中間元素
實現如下:
if (i_list.size()%2 != 0)//如果鏈表size為奇數則打印正中間元素
{
for (size_t i = 1; i < (i_list.size() + 1)/2; ++i)//從鏈表第一個元素開始到鏈表長度一半的偏移量
{
tar_it++;
}
cout << "鏈表的中間元素為:"???????? << *tar_it << endl;
}
else//如果鏈表size為偶數則打印中間兩個元素
{
for (size_t i = 1; i < i_list.size()/2 ; ++i) //從鏈表第一個元素開始到鏈表長度一半的偏移量
{
tar_it++;
}
cout << "鏈表的中間元素為:"???????? << *tar_it << "和";
tar_it++;
cout << *tar_it << endl;
}
?
4.找到不為0的元素,插入到vector,并打印
聲明vector,置空
遍歷list 判斷元素是否為0,不為0則插入到vector
遍歷vector輸出每個元素
實現如下:
vector<int> i_vector;
i_vector.clear();
for (auto it = i_list.begin(); it != i_list.end(); ++it)
{
if (*it != 0)//不為0的元素
{
i_vector.push_back(*it);
}
}
cout << "將不為0的元素拷貝到vector中后打印結果如下:" << endl;
for (auto value: i_vector)
{
cout << value << " ";
}
?