C++STL與泛型編程高級 學習筆記(自查用)

https://www.bilibili.com/video/av48068999?p=5
記錄一些在裏面提到的函數用法例子

第一講 容器


  • 讀取時間
#include <ctime>
clock_t timeStart = clock();//單位ms
//...
cout << "milli-seconds:" << (clock() - timeStart) << endl;

-排序(list等不能用std::sort)

array<long, ASIZE> c;
for (long i = 0; i < ASIZE; ++i) {
		    c[i] = rand() % 65535;
		}
qsort(c.data(), ASIZE, sizeof(long), compareLongs);
  • 二分查找
#include<cstdlib>
int compareLongs(const void* a, const void* b)
{
    return (*(long*)a - *(long*)b);
}
long* pItem = (long*)bsearch(&target, (c.data()), ASIZE, sizeof(long), compareLongs);
		cout << "bsearch(), milli-seconds: " << (clock() - timeStart) << endl;
		
		if (pItem != NULL)
			cout << "found, " << *pItem << endl;
		else
			cout << "not found!" << endl;

將數字轉化爲char,再轉換爲string

#include<cstdio>
char buf[10];
snprintf(buf, 10, "%d", rand() % 65535);
cout<<string(buf);

在vector中find

auto pItem = find(c.begin(),c.end(),target);
if(pItem !- c.end())
	cout<<"find:"<<*pItem<<endl;
else
	cout<<"not find"<<endl;

在vector中用二分查找

vector<string> c;
sort(c.begin(),c.end());

int compareStrings(const void* a, const void* b)
{
    if (*(string*)a > *(string*)b)
	    return 1;
    else if(*(string*)a < *(string*)b)
	    return -1;
    else
	    return 0;
}

string* pItem = (string*)bsearch(&target, (c.data()), c.size(), sizeof(string), compareStrings);
if (pItem != NULL)
			cout << "found, " << *pItem << endl;
		else
			cout << "not found!" << endl;
  • bsearch 函數使用說明
void *bsearch(const void *key, const void *base, size_t nitems, size_t size, int (*compar)(const void *, const void *))

key -- 指向要查找的元素的指針,類型轉換爲 void*。
base -- 指向進行查找的數組的第一個對象的指針,類型轉換爲 void*。
nitems -- base 所指向的數組中元素的個數。
size -- 數組中每個元素的大小,以字節爲單位。
compar -- 用來比較兩個元素的函數。
  • 某些容器自帶sort,例如list ,forward_list,
list<string> c;
c.sort();
  • 某些容器自帶find,如set,multiset,map,
  • multimap,unordered_multiset,unordered_multimao
auto pItem = c.find(target);//更快!!!!!!!!!!
auto pItem = find(c.begin(),c.end(),target);
  • 分配器allocator
#include<memory>
包含了std::allocator
此外gnu還有大量的非標分配器
如
#include<ext/array_allocator.h>
#include<ext/mt_allocator.h>
#include<ext/debug_allocator.h>

第二講 容器

oop(object-oriented programming )vs GP(generic programming)
面向對象編程與模板編程
GP思維:容器containers和算法algorighms各自管自己,再通過Iterator迭代器聯結.
所有的算法,其中涉及元素本身的操作就是比大小
例子:比大小

strLonger(const string& s1,const string& s2)
{
	return s1.size() < s2.size();
}
cout<<"longest: "<<max(string("zoo"),string("hello",strLonger));//輸出hello

基礎:
操作符重載 overloaded operators
節選一段list文件中的重載:

template<class _Mylist,
	class _Base = _Iterator_base0>
	class _List_unchecked_const_iterator
		: public _Iterator012<bidirectional_iterator_tag,
			typename _Mylist::value_type,
			typename _Mylist::difference_type,
			typename _Mylist::const_pointer,
			typename _Mylist::const_reference,
			_Base>
	{	// unchecked iterator for nonmutable list
public:
	typedef _List_unchecked_const_iterator<_Mylist, _Base> _Myiter;
	typedef bidirectional_iterator_tag iterator_category;

	typedef typename _Mylist::_Nodeptr _Nodeptr;
	typedef typename _Mylist::value_type value_type;
	typedef typename _Mylist::difference_type difference_type;
	typedef typename _Mylist::const_pointer pointer;
	typedef typename _Mylist::const_reference reference;

	_List_unchecked_const_iterator()
		: _Ptr(0)
		{	// construct with null node pointer
		}

	_List_unchecked_const_iterator(_Nodeptr _Pnode, const _Mylist *_Plist)
		: _Ptr(_Pnode)
		{	// construct with node pointer _Pnode
		this->_Adopt(_Plist);
		}

	reference operator*() const
		{	// return designated value
		return (_Mylist::_Myval(_Ptr));
		}

	pointer operator->() const
		{	// return pointer to class object
		return (_STD pointer_traits<pointer>::pointer_to(**this));
		}

	_Myiter& operator++()
		{	// preincrement
		_Ptr = _Mylist::_Nextnode(_Ptr);
		return (*this);
		}

	_Myiter operator++(int)
		{	// postincrement
		_Myiter _Tmp = *this;
		++*this;
		return (_Tmp);
		}

	_Myiter& operator--()
		{	// predecrement
		_Ptr = _Mylist::_Prevnode(_Ptr);
		return (*this);
		}

	_Myiter operator--(int)
		{	// postdecrement
		_Myiter _Tmp = *this;
		--*this;
		return (_Tmp);
		}

	bool operator==(const _Myiter& _Right) const
		{	// test for iterator equality
		return (_Ptr == _Right._Ptr);
		}

	bool operator!=(const _Myiter& _Right) const
		{	// test for iterator inequality
		return (!(*this == _Right));
		}

	_Nodeptr _Mynode() const
		{	// return node pointer
		return (_Ptr);
		}

	_Nodeptr _Ptr;	// pointer to node
	};
  • 基礎知識:類模板 cass templates
template <typename T>
class complex
//複數類
{
public:
	complex(T r = 0, T i = 0): re(r), im (i)
	{}
	complex& operator +=(const complex&);
	T real () const{ return re;}
	T imag () const {return im;} 
private:
	T re,im;
}


/***********使用**********************/
complex<double> c1(2.5,1.5);
  • 基礎知識:模板函數 function templates
template <class T>
inline
const T& min(const T& a,const T& b)
{
	return b < a? b : a;
}
  • 基礎知識:特化 specialization
    對具體模板寫對應的特化,如
template<> struct hash<bool>;
template<> struct hash<char>;
template<> struct hash<signed char>;
template<> struct hash<unsigned char>;
template<> struct hash<char8_t>;        // C++20
template<> struct hash<char16_t>;
template<> struct hash<char32_t>;
template<> struct hash<wchar_t>;
template<> struct hash<short>;
template<> struct hash<unsigned short>;
template<> struct hash<int>;
template<> struct hash<unsigned int>;
template<> struct hash<long>;
template<> struct hash<long long>;
template<> struct hash<unsigned long>;
template<> struct hash<unsigned long long>;
template<> struct hash<float>;
template<> struct hash<double>;
template<> struct hash<long double>;
template<> struct hash<std::nullptr_t>; // C++17
template< class T > struct hash<T*>;
  • 偏特化 partial specialization(個數,範圍(是否指針,是否const)兩種偏特化方式)
template<class Alloc>
class vector<bool,Alloc>
{
...
}

//對應泛化
template <class T,class Alloc = alloc>
class vector
{...}
  • 分配器
  • 使用容器的時候會調用分配器來分配內存。
  • vc6+中的 allocator 只是通過new和delete來完成allocate()和deallocate(),沒有特殊設計。
  • 在這裏插入圖片描述
  • 舉個例子直接調用allocator(一般不直接用)
//分配512ints
int *p = allocator<int>().allocate(512,(int*)0);//創建
allocator<int>().deallocate(p,512);//釋放

不做任何處理的分配器會導致在大量malloc的時候產生cookie的額外開銷。
G 2.9 stl中對alloc進行了優化:減少malloc的次數。
現在在G4.9中優化方法改名爲pool_alloc,使用方法:

vector<string,gnu_cxx::_pool_alloc<string>> vec;
  • 容器結構分類:
    在這裏插入圖片描述
    裏面的大小指控制所需,並不是每個元素的大小。

list

G2.9
在這裏插入圖片描述
在這裏插入圖片描述
4.9優化
在這裏插入圖片描述
Iterator提供5種associate types:
在這裏插入圖片描述
ptrdiff_t指的是兩個指針的距離的類型,這就限制了容器的大小。

  • Iterator Traits(特性)
  • 可以區分class iterators與non-class iterators
  • 在這裏插入圖片描述

Vector

在這裏插入圖片描述
兩倍增長:
在這裏插入圖片描述
做了兩次檢測,是因爲insert_aux在別處也有被調用,比如insert等調用它。
在這裏插入圖片描述

deque

通過map對空間索引實現前後區域的擴展。
在這裏插入圖片描述

queue和stack

都不提供iterator
底層可以通過deque或者list封裝實現,stack也可以用vector做底層結構
注意使用時pop,push,不帶back或者front。

rb_tree

提供兩種insert操作,insert_unique()或者insert_equal()
在這裏插入圖片描述


第三講 算法

算法通過模板函數實現
在這裏插入圖片描述

在這裏插入圖片描述
bidirectional 雙向
紅黑樹生成的都是雙向迭代器
hash_table生成的容器用單項迭代器

find:
在這裏插入圖片描述
for_each:
在這裏插入圖片描述
count:
在這裏插入圖片描述
sort:
在這裏插入圖片描述
bineary_search:返回真/假
在這裏插入圖片描述
二分查找可以直接用lower_bound:他返回一個在first與last迭代器區間[first,last)內第一個不小於val的元素。


仿函數functors

爲算法提供服務,添加一些準則等,比如排序順序等
在這裏插入圖片描述
仿函數要繼承unary單參數或者binary雙參數來,以便被適配器後續改造。
在這裏插入圖片描述


適配器adapter

包含: 容器適配器,迭代器適配器,仿函數適配器

在這裏插入圖片描述

容器適配器:

在這裏插入圖片描述

函數適配器:

在這裏插入圖片描述
相當於將第二個參數綁定爲固定的,比如less()需要比較兩個參數大小,這裏就可以把第二個參數綁定爲40。但是bind在c++11已經改版了:
在這裏插入圖片描述
函數適配器not1,傳遞判斷條件,取非輸出.
在這裏插入圖片描述

新型適配器bind

在這裏插入圖片描述
cbegin()表示const型begin迭代器
舉個例子:


#include <iostream>
#include <functional>
#include <vector>
#include <algorithm>
using namespace std;
using namespace std::placeholders;

int main()
{
	vector<int> v{15,32,243,234,51,50,12};
	auto fn_ = bind(less<int>(),_1,50);
	cout << count_if(v.cbegin(), v.cend(), fn_) << endl;
	cout << count_if(v.cbegin(), v.cend(), bind(less<int>(), _1, 50) )<< endl;

	system("pause");
}

迭代器適配器

在這裏插入圖片描述

在這裏插入圖片描述

X(未知)適配器

ostream_iterator
測試一下:


#include <iostream>
#include <functional>
#include <vector>
#include <algorithm>
#include <iterator>
using namespace std;
using namespace std::placeholders;

int main()
{
	vector<int> v{15,32,243,234,51,50,12};
	ostream_iterator<int> out_it(cout, ",");
	copy(v.begin(), v.end(), out_it);
	system("pause");
}

在這裏插入圖片描述
在這裏插入圖片描述
測試一下:

#include<iostream>
#include<string>
#include<iterator>
#include<algorithm>
using namespace std;
int main()
{
	string text;
	istream_iterator<int> is(cin);//綁定標準輸入裝置
	istream_iterator<int> eof;//定義輸入結束位置
	copy(is, eof, back_inserter(text));
	sort(text.begin(), text.end());

	ostream_iterator<int> os(cout, ", ");//綁定標準輸出裝置
	copy(text.begin(), text.end(), os);
	system("pause");
}

在這裏插入圖片描述


第四講 應用

tuple元組
#include <iostream>  
#include <vector>  
#include <string>  
#include <tuple>  

using namespace std;

std::tuple<std::string, int>
giveName(void)
{
	std::string cw("Caroline");
	int a(2013);
	std::tuple<std::string, int> t = std::make_tuple(cw, a);
	return t;
}

int main()
{
	std::tuple<int, double, std::string> t(64, 128.0, "Caroline");
	std::tuple<std::string, std::string, int> t2 =
		std::make_tuple("Caroline", "Wendy", 1992);

	//返回元素個數  
	size_t num = std::tuple_size<decltype(t)>::value;
	std::cout << "num = " << num << std::endl;

	//獲取第1個值的元素類型  
	std::tuple_element<1, decltype(t)>::type cnt = std::get<1>(t);
	std::cout << "cnt = " << cnt << std::endl;

	//比較  
	std::tuple<int, int> ti(24, 48);
	std::tuple<double, double> td(28.0, 56.0);
	bool b = (ti < td);
	std::cout << "b = " << b << std::endl;

	//tuple作爲返回值  
	auto a = giveName();
	std::cout << "name: " << get<0>(a)
		<< " years: " << get<1>(a) << std::endl;
	system("pause");
	return 0;
}

在這裏插入圖片描述

在這裏插入圖片描述
遞歸繼承
在這裏插入圖片描述

type traits 類型萃取

在這裏插入圖片描述
trivial:不重要的。
在這裏插入圖片描述
舉個例子:

#include <iostream>

using namespace std;

class Parent{};
class Child : public Parent{}; //class Child : Parent{},爲private繼承
class Alone{};

int main()
{
	cout << std::boolalpha; //以下的0、1按false和true格式輸出

	/*基本的type_traits用法*/
	cout << is_const<int>::value << endl;         //false
	cout << is_const<const int>::value << endl;   //true
	cout << is_const<const int&>::value << endl;  //false
	cout << is_const<const int*>::value << endl;  //false
	cout << is_const<int* const>::value << endl;  //true

	/*is_same用法*/
	cout << is_same<int, int>::value << endl;         //true
	cout << is_same<int, unsigned int>::value << endl;//false
	cout << is_same<int, signed int>::value << endl; //true

	/*is_base_of*/
	cout << is_base_of<Parent, Child>::value << endl; //true
	cout << is_base_of<Child, Parent>::value << endl; //false
	cout << is_base_of<Parent, Alone>::value << endl; //false

	/*is_convertible<From, To>用法:判斷From類型是否可以轉爲To類型*/
	cout << is_convertible<Parent*, Child*>::value << endl; //false
	cout << is_convertible<Child*, Parent*>::value << endl; //true
	cout << is_convertible<Parent*, Alone*>::value << endl; //false    
	return 0;
}

type traits的實現
在這裏插入圖片描述

cout

在這裏插入圖片描述

moveable對效率的影響

在這裏插入圖片描述
其他的差別不大。


完結撒花~~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章