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(){ //程序抽象成一个container
int ia[6] = {127, 50, 90, 60, 30, 10};
vector<int, allocator<int>> vi(ia, ia+6); //vi.begin()抽象成iterators
cout<< cout_if(vi.begin(), vi.end(), not1(bind2nd(less<int>(), 40)));//这系列函数即count_if为algorithms,not1为function

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;
}