c++_stl,map,unordered_map

map/unordered_map的下标操作

template< _KeyType, _MappedType>
class [unordered_]map{
	
	_MappedType & operator[]( const _KeyType & _k){
		iterator i = find( _k);
		if( i == end())
			i = mp.insert( {_k, _MappedType()});
		return (*i).second;
	}
}

[unordered_]map< int, Foo> mp
mp[ 1] = Foo()

此时, &mp[ 1] 就是mp里元素的地址!!!

&mp[ 0] 他会, 往mp里, 插入一个{0, Foo()}

-------------------------------

介绍

C++ Standard Lib: 标准库
Standard Template Lib: 标准'模板'库
  标准库 > STL, 但STL占据C++标准库的80%

只要有”编译器",就一定自带有”C++标准库“
C++标准库,是以”header头文件“的形式存在
  标准库里的东西,都被放在 ”std“这个命名空间里。

不管是什么编译器gnu/vc,他们肯定会自带C++标准库
   对标准库的使用,几乎100%是一样的。

学习网站

http://cplusplus.com/
https://en.cppreference.com/w/
https://gcc.gnu.org/onlinedocs/

STL

介绍

STL的6大部件:
	1,容器 (重要)
	2,算法 (重要)
	3,分配器
	4,迭代器
	5,适配器
	6,仿函数

仿函数

一元函数unary_function

  template<typename _Arg, typename _Result>
    struct unary_function
    {
      typedef _Arg 	argument_type;   
      typedef _Result 	result_type;  
    };
' 形如:   _Result r = func( a ); '
' 这个类,是基类。 仅仅规范了, 返回值 和 参数 的类型!! '
'   具体,这个func怎么设计, 由子类完成 '

二元函数binary_function

template<typename _Arg1, typename _Arg2, typename _Result>
    struct binary_function
    {
      typedef _Arg1 	first_argument_type; 
      typedef _Arg2 	second_argument_type;
      typedef _Result 	result_type;
    };
' 形如: _Result r = func( a, b ); '

plus

  template<typename _Tp = void>
    struct plus;

  template<typename _Tp>
    struct plus : public binary_function<_Tp, _Tp, _Tp>
    { ' 继承自binary_func,即由2个参数 + 1个返回值 组成 '
      _GLIBCXX14_CONSTEXPR
      _Tp operator()(const _Tp& __x, const _Tp& __y) const
      { return __x + __y; }
    };

int ret = plus<int>()(3, 4);
' 不要写成: plus<int>(3, 4),这是在调用构造函数!!! '

上述代码等价于: 
plus<int> obj;
int ret = obj(3, 4); 

negate

  template<typename _Tp = void>
    struct negate;
    
  template<typename _Tp>
    struct negate : public unary_function<_Tp, _Tp>
    { ' 继承自unary_,即由1个参数 + 1个返回值 组成 '
      _GLIBCXX14_CONSTEXPR
      _Tp
      operator()(const _Tp& __x) const
      { return -__x; }
    };

int ret = negate<int>()(5);  ' 不要忘记前面的(),是在构造一个对象 '

less

  template<typename _Tp = void>
    struct less;

  template<typename _Tp>
    struct less : public binary_function<_Tp, _Tp, bool>
    {
      _GLIBCXX14_CONSTEXPR
      bool
      operator()(const _Tp& __x, const _Tp& __y) const
      { return __x < __y; }
    };
' heap就默认使用的这个less, 2个参数(a, b):  heap.top是其中的b!! '

适配器

函数适配器bind2nd

bind2nd的作用:
   我们已经写好了less这个仿函数,即less(a, b){ return a < b; }
   但是,如果说我们想要让 a或b,是一个常数固定值,而不是一个变量。
  
比如,每次都是less(a, 10): 
  此时,这个函数,变成只有1个变量!!! 
  原来他是2元函数,现在变成了1元函数!!!
  即,从binary_func -> unary_func 的转换(适配)。

  template<typename _Operation, typename _Tp>
    binder2nd<_Operation>
    bind2nd(const _Operation& __fn, const _Tp& __x)
    {
      typedef typename _Operation::second_argument_type _Arg2_type;
      return binder2nd<_Operation>(__fn, _Arg2_type(__x));
    }
1, bind2nd是个函数!!!  它可以模板参数推演,可以不写模板
	即” 适配器 ” 是个 函数!!!  “仿函数”是个类!!!
2, 他默认你传入的_Operation这个”类型“,是继承自binary_function的
	 因为只有继承自binary_function,他才有second_argument_type这个typedef
3, 他的返回值 是一个”对象“
4, 使用: bind2nd<类型, 类型>( 对象, 对象 );
    __fn是一个对象!! 即一个仿函数的对象。


再看,这个返回值,binder2nd:
   template<typename _Operation>
    class binder2nd
    : public unary_function<typename _Operation::first_argument_type,
			    typename _Operation::result_type>
    { ' 他是个类(即,仿函数),因为第二参数固定了,所以是一元函数 '
    protected:
      _Operation op; ' _Operation即是”你原来的 二元函数“ '
      typename _Operation::second_argument_type value;
      ' op 和 value,这是2个对象。 对应构造函数传入的2个参数 '

    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); }
      ' 仿函数:  他只需要1个参数!!! 即1个变量,每次和value这固定值 比较 '
      '          比较的策略, 即是你原来的2元函数op '
      ' 这个op(a, b),就是在调用: op这个类里的 对()的操作符重载,即”仿函数" '




less<int> obj;
binder2nd< less<int> > ret = bind2nd< less<int>, int >( obj, 6 );
int ans = count_if( VE_ALL(A) , ret );
 ' ans 为,A中 所有 < 6 的元素个数。 '


allocator源码

template<typename _Tp>
class allocator: public __allocator_base<_Tp>
{
	allocator() throw() { }
}
' 可以看出,allocator这个类的使用 很简单,只是构造一个对象而已 '
即: allocator<int> obj;
' 关键是要看,他的父类 __allocator_base '

namespace std
{
  template<typename _Tp>
    using __allocator_base = __gnu_cxx::new_allocator<_Tp>;
} ' 即默认的allocator,使用的是: new_allocator '

template<typename _Tp>
class new_allocator
{
	new_allocator() { }
	
	size_t max_size() const { return size_t(-1) / sizeof(_Tp); }
	' size_t(-1) = 2^32 - 1 '

	_Tp* allocate(size_type __n, const void* = 0)
    { 
		if (__n > this->max_size())  std::__throw_bad_alloc();
		return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp)));
    }

	void deallocate(pointer __p, size_t){ ::operator delete(__p); }
	' 虽然第二参数没有用到,但是你还需要得填!!! '
}

使用

allocator<int> alloc;

int* arr = alloc.allocate(10); // arr[0, 9]

alloc.deallocate(arr, 10);

' 我们知道,delete/free时 是不用知道 这个指针 当初是new了几个 '
 直接free这个指针即可,delete arr,并不需要知道该指针当初new了几个
 但是deallocate却需要我们去记忆 你当初是申请了几个元素
 ' 这太麻烦了, 谁能记得住.....  '

所以说明, 并不建议 直接使用allocator来申请内存!!!
 他是配合“容器”来使用的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值