C++11语法
1 2 3 4 5 6 7 8 9 10 11 12
| --------------------game1------------------------------- for ( int i : {2, 3, 4}) { std::cout << i << std::endl; } -----> std::vector<double> vec: ... for( auto elem : vec) { std::cout << elem << std::end; } ---------------------------------------------------------
|
level-0
STL体系基础
新式header不带有.h后缀
using namespace std相当于打开std的空间例如可以使用cout而不使用std::cout
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| #include <vector> #include <algorithm> #include <functional> #include <iostream>
using namespace std;
int main(){ int ia[6] = {127, 50, 90, 60, 30, 10}; vector<int, allocator<int>> vi(ia, ia+6); cout<< cout_if(vi.begin(), vi.end(), not1(bind2nd(less<int>(), 40))); return 0; }
|
容器遵守前闭后开规则,off by one(这个还比较熟悉:))
测试单元文件可以使用namespace{}
分配器的测试及使用
1 2 3
| --------------特殊的分配器使用例子--------------------------------- #include <ext\xxxx_allocator.h> list<string, _gnu_cxx::xxxx_allocator<string>> c1
|
level-1
GP编程是datas和methods分开例如
1 2 3 4 5 6 7
| template<class T, class Alloc=alloc> class vector { ...... }; void sort(){ ..... }
|
OOP编程是datas和methods合并在一起例如
1 2 3 4 5 6 7
| template<class T, class Alloc=alloc> class vector { ...... void sort(){ ..... } };
|
特化版本中__STL_TEMPLATE_NULL等于template<>
分配器
1 2 3 4 5 6 7
| 内存分配调用allocate->operator new->malloc #pwn的调用链还挺相似的:) house of allocate ---------------------vc++中的关于allocate源码例子(不同标准库不同)------------------ int *p = allocator<int>().allocate(512, (int*)0); allocator<int>().deallocate(p, 512); #deallocate相对应的free ---------------------gcc2.9中的关于allocate源码例子(相对常见的一种)---------------- void *p = alloc::allocate(512); alloc::deallocate(p, 512);
|
探索list
1 2 3 4 5
| self operator++(int) {self tmp = *this; ++*this; return tmp} #i++形式 self& operator++() {node = (link_type)(*(node.next)); return *this} #++i形式 为什么后++是self&,因为要模仿i++(i为整数时候的格式) #规则中允许++++i,不允许i++++,前者传递是指针才行
|
前闭后开的设置情况,会在环状结构的末尾会多出一个空的单位
迭代器
1 2 3 4 5 6 7 8 9 10
| template<class T, class Ref, class Ptr> struct __list_iterator { typedef bidirectional_iterator_tag iterator_catergory;#1表示分类,例如单向加加减减或者双向根据容器决定 typedef T value_type;#2 typedef Ptr pointer;#3 typedef Ref reference;#4 typedef ptrdiff_t difference_type;#5表示距离 }#算法必须回答迭代器以上五个type
|
如果传进参数不是class模板的值例如 list::iterator :alien: 而是例如T*,这时候就要调用iterator traits
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| template<class I> struct iterator_traits { typedef typename I::value_type value_type; }; template<class T> struct iterator_traits<T*> { typedef T value_type; }; template<class T> struct iterator_traits<const T*> { typedef T value_type; };#注意value不能设置为一个固定的指针 ... template<typename I,...> void algorithm(...) { typename iterator_traits<I>::value_type v1; #回答了5个type问题中的一个问题 } #分类I为不同情况下的偏特化
|
完整的iterator_traits例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| template <class T> struct iterator_traits { typedef typename I::iterator_category iterator_category; typedef typename I::value_type value_type; typedef typename I::difference_type difference_type; typedef typename I::pointer pointer; typedef typename I::reference reference; } --------------------- template <class T> struct iterator_traits<const T*> { typedef random_access_iterator_tag iterator_category; typedef typename T value_type; typedef typename ptrdiff_t difference_type; typedef typename T* pointer; typedef typename T& reference; }; #整体给我一种像是protobuf一样的必须是格式化输出输出的感觉:)
|
容器探索
设计上使用两层或者多层调用,例如T size = I.finish() - I.start();
GCC4.x版本和GCC2.x版本差距真是太大了,总结一句究极套娃:alien:
c++11以后hash_set,hash_map之类都改成了unordered_set, unordered_map
level-2
算法探索
容器算法的选择例子:baby:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| template<class ForwardIterator, class T> void replace(ForwardIterator first, ForwardIterator last, const T& old_value, const T& new_value){ for(;first != last; ++first) if(*first == old_value) *first = new_value; } ---------------------------------------------------------- template<class ForwardIterator, class T> void replace_if(ForwardIterator first, ForwardIterator last, Predicate pred, const T& new_value){ for(;first != last; ++first) if(pred(*first)) *first = new_value; }
|
特殊的算法lower_bond&upper_bond
1 2 3 4 5 6 7
| low = lower_bound(v.begin(), v.end(), 20) up = upper_bound(v.begin(), v.end(), 20) ---------------------------------------------- 10 10 10 20 20 20 20 20 30 30 <-20 | | lower插入20的最低点 upper插入20的最高点 针对已经排好序的进行二分搜寻法
|
仿函数
考虑到程序的复用有时方便会使用仿函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| template <class Arg1, class Arg2, class Result> struct binary_function{ typedef Arg1 first_argument_type; typedef Arg2 second_argument_type; typedef Result Result_type; }
template <class T> struct myclass:public binary_function(T, T, bool){ bool operator()(const T &x,const T &y){return x < y;} }myobj; #关键字operator实现了仿函数的功能
sort(myvee.begin(), myvee.end(), myobj<int>); sort(myvee.begin(), myvee.end(), sort<int>); ---------------------------------------------------------------
|
函数适配器
算是前几章的综合利用了:baby_bottle:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
| cout<< cout_if(vi.begin(), vi.end(), not1(bind2nd(less<int>(), 40))); #来自level-0的STL体系的例子 #以下是not1的调用链梳理 bind2nd->binder2nd-> ->op->less<int> value->40 secon_argument_type->int-> ->binder2nd(仿函数调用)-> ->pred(*first)->less<int>(int, 40); ->no1->unary_negate(仿函数调用)-> ->!less<int>(int, 40); #下面是具体函数 ------------------------------------------------------------------------------------------------------------------ template<class Predicate> inline unary_negate<Predicate> not1(const Predicate& pred){ return unary_negate<Predicate>(pred); } ------------------------------------------------------------------------------------------------------------------- template<class Predicate> class unary_negate:public unary_function<typename Predicate::argument_type, bool>{ protected: Predicate pred; public: explict unary_negate(const Predicate& x):pred(x){} bool operator()(const typename Predicate::argument_type& x)const { return !pred(x); } }; ------------------------------------------------------------------------------------------------------------------- template<class Operation, class T> inline binder2nd<Operation>bind2nd(const Operation& op, const T& x){ typedef typename Operation::second_argument_type arg2_type; return binder2nd<Operation>(op, arg2_type(x)); } ------------------------------------------------------------------------------------------------------------------- template<class Operation> class binder2nd: public unary_function< typename Operation:first_argment_type typename Operation:result_type>{ protected: Operation op; typename Operation::second_argument_type value; public: binder2nd(const Operation& x, const typename Operation::second_argument_type& y) :op(x),value(y){} typename Operation::result_type operator()(const typename Operation::first_argument_type& x)const{ return op(x, value); } }; -------------------------------------------------------------------------------------------------------------------template<class InputIterator, class Predicate> typename iterator_trait<InputIterator>::difference_type count_if(InputIterator first, InputIterator last, Predicate pred){ typename iterator_trait<InputIterator>::difference_type n = 0; for(; first != last; ++first) if(pred(*first)) n++; return n; } -------------------------------------------------------------------------------------------------------------------
|
迭代器分配器
一种重构已有函数的方法,有点奇妙
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| copy(bar.begin(), bar.end(), inserter(foo,it)); --------------------------------------------------------------------------------------------------------- template<class InputIterator, class OutputIterator> copy(InputIterator first, InputIterator last, OutputIterator result){ while(first != last){ *result = *first; #可以看到copy的第三个参数并不是一个函数,一个新的方法就是重构= ++result;++first; } return result; } #首先是一个辅助函数 template<class Container, class Iterator> inline insert_iterator<Container> inserter(Container& x,Iterator i){ typedef typename Container::iterator iter; return insert_iterator<Container>(x, i); } #之后对=进行重构 template<class Container> class insert_iterator{ ... operator = (const typename Container::value_type& value){ iter = container->insert(iter, value); ++iter; return *this; } } #同理++result也是相似的
|
小总结
:baby_bottle:看了那么多适配器感觉可以稍稍总结出一个规律(不一定是XD)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| template<class T> T Sample_Function_Adapter(T &x){ typedef typename T; return Sample_Function(x); } template<class T> class Sample_function(T &x){ T_type x; protected: typedef T_type Ttype; public: Sample_Function(Ttype y):T_type(y){}
T_type operator(){return x}; }
|
level-3
可变参数递归思考
哈希函数通过递归调用的方式进行哈希加密,可变参数参考:https://blog.csdn.net/m0_69442905/article/details/131747258
1 2 3 4 5
| template<typename T, typename... Types> inlint void hash_val (size & seed, const T& val, const Types&... args){ hash_combine(seed, val); hass_val(seed, args...); }
|
tiuple分析
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| template<> class tuple<>{} template<typename Head, typename... Tail> class tuple<Head, Tail...> : private tuple<Tail...> { typedef tuple<Tail...> inherited; public: tuple(){} tuple(Head v, Tail... vtail):m_head(v),inherited(vtail...){} typename Head::type head() {return m_head;} inherited& tail() {return *this;} protected: Head m_head; }
tuple(6.3, 41, "hello"); #根据可变参数分析以上函数可得到 #tuple<float, int, string> int m_head(6.3) -> tuple<int, string> float m_head(41) -> tuple<string> string m_head("hello") -> tuple<>()
|
type_traits实现
1 2 3 4 5 6 7 8 9 10 11 12 13
| template<typename _Tp> struct remove_const<_Tp const> {typedef _Tp type;};
template<typename _Tp> struct remove_volatile<_Tp volatile> {typedef _Tp type;};
template<typename _Tp> struct remove_cv { typedef typename remove_const<typename remove_volatile<_Tp>::type>::type type; }
|