操作系统:centos 6.4
STL源码版本:3.3

前言:
    要看一个项目的源码,首先要选中切入点。
    那么在sgi stl 标准库中,其切入点是什么呢?
    答案是:stl_config.h 文件。

不同的编译器对C++语言的支持程度不尽相同。为了具备广泛移植能力,SGI STL  定义了一个环境组态文件<stl_config.h>。
其中声明了许多宏定义,在预编译的时候,通过这些宏定义来编译出对于平台的程序。

1,stl_config.h在linux平台下的实现:
    
    1.1)为了知道linux平台下sgi stl 的宏定义有那些是被定义了的,有个简单,直接的方法,直接输出其宏名字。
        测试代码如下:

#include <iostream>
#include <stdio.h>
using namespace std;void    test(void)
{
#ifdef _PTHREADScout<<"define __STL_PTHREADS"<<endl;
#endif# if defined(__sgi) && !defined(__GNUC__)cout<<"__sgi begin"<<endl;
# if !defined(_BOOL)cout<<"__STL_NEED_BOOL"<<endl;
# endif
# if !defined(_TYPENAME_IS_KEYWORD)cout<<"__STL_NEED_TYPENAME"<<endl;
# endif
# ifdef _PARTIAL_SPECIALIZATION_OF_CLASS_TEMPLATEScout<<"__STL_CLASS_PARTIAL_SPECIALIZATION"<<endl;
# endif
# ifdef _MEMBER_TEMPLATEScout<<"__STL_MEMBER_TEMPLATES"<<endl;
# endif
# if !defined(_EXPLICIT_IS_KEYWORD)cout<<"__STL_NEED_EXPLICIT"<<endl;
# endif
# ifdef __EXCEPTIONScout<<"__STL_USE_EXCEPTIONS"<<endl;
# endif
# if (_COMPILER_VERSION >= 721) && defined(_NAMESPACES)cout<<"__STL_USE_NAMESPACES"<<endl;
# endif
# if !defined(_NOTHREADS) && !defined(__STL_PTHREADS)cout<<"__STL_SGI_THREADS"<<endl;
# endifcout<<"__sgi end"<<endl<<endl;
# endif# ifdef __GNUC__cout<<"__GNUC__ begin"<<endl;
# include <_G_config.h>
# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8)cout<<"__STL_STATIC_TEMPLATE_MEMBER_BUG"<<endl;cout<<"__STL_NEED_TYPENAME"<<endl;cout<<"__STL_NEED_EXPLICIT"<<endl;
# elsecout<<"__STL_CLASS_PARTIAL_SPECIALIZATION"<<endl;cout<<"__STL_FUNCTION_TMPL_PARTIAL_ORDER"<<endl;cout<<"__STL_EXPLICIT_FUNCTION_TMPL_ARGS"<<endl;cout<<"__STL_MEMBER_TEMPLATES"<<endl;
# endif/* glibc pre 2.0 is very buggy. We have to disable thread for it.It should be upgraded to glibc 2.0 or later. */
# if !defined(_NOTHREADS) && __GLIBC__ >= 2 && defined(_G_USING_THUNKS)cout<<"__STL_PTHREADS"<<endl;
# endif
# ifdef __EXCEPTIONScout<<"__STL_USE_EXCEPTIONS"<<endl;
# endifcout<<"__GNUC__ end"<<endl<<endl;
# endif# if defined(__SUNPRO_CC) cout<<"__SUNPRO_CC begin"<<endl;cout<<"__STL_NEED_BOOL"<<endl;cout<<"__STL_NEED_TYPENAME"<<endl;cout<<"__STL_NEED_EXPLICIT"<<endl;cout<<"__STL_USE_EXCEPTIONS"<<endl;cout<<"__SUNPRO_CC end"<<endl<<endl;
# endif# if defined(__COMO__)cout<<"__COMO__ begin"<<endl;cout<<"__STL_MEMBER_TEMPLATES"<<endl;cout<<"__STL_CLASS_PARTIAL_SPECIALIZATION"<<endl;cout<<"__STL_USE_EXCEPTIONS"<<endl;cout<<"__STL_USE_NAMESPACES"<<endl;cout<<"__COMO__ end"<<endl<<endl;
# endif# if defined(_MSC_VER)
cout<<"_MSC_VER begin"<<endl;
# if _MSC_VER > 1000cout<<"include <yvals.h>"<<endl;
# elsecout<<"__STL_NEED_BOOL"<<endl;
# endifcout<<"__STL_NO_DRAND48"<<endl;cout<<"__STL_NEED_TYPENAME"<<endl;
# if _MSC_VER < 1100cout<<"__STL_NEED_EXPLICIT"<<endl;
# endifcout<<"__STL_NON_TYPE_TMPL_PARAM_BUG"<<endl;cout<<"__SGI_STL_NO_ARROW_OPERATOR"<<endl;
# ifdef _CPPUNWINDcout<<"__STL_USE_EXCEPTIONS"<<endl;
# endif
# ifdef _MTcout<<"__STL_WIN32THREADS"<<endl;
# endifcout<<"_MSC_VER end"<<endl<<endl;
# endif# if defined(__BORLANDC__)cout<<"__BORLANDC__ begin"<<endl;cout<<"__STL_NO_DRAND48"<<endl;cout<<"__STL_NEED_TYPENAME"<<endl;cout<<"__STL_LIMITED_DEFAULT_TEMPLATES"<<endl;cout<<"__SGI_STL_NO_ARROW_OPERATOR"<<endl;cout<<"__STL_NON_TYPE_TMPL_PARAM_BUG"<<endl;
# ifdef _CPPUNWINDcout<<"__STL_USE_EXCEPTIONS"<<endl;
# endif
# ifdef __MT__cout<<"__STL_WIN32THREADS"<<endl;
# endifcout<<"__BORLANDC__ end"<<endl<<endl;
# endif# if defined(__STL_NEED_BOOL)cout<<"__STL_NEED_BOOL begin"<<endl;cout<<"typedef int bool;"<<endl;cout<<"define true 1"<<endl;cout<<"define false 0"<<endl;cout<<"__STL_NEED_BOOL end"<<endl<<endl;
# endif# ifdef __STL_NEED_TYPENAMEcout<<"define typename"<<endl;
# endif# ifdef __STL_NEED_EXPLICITcout<<"define explicit"<<endl;
# endif# ifdef __STL_EXPLICIT_FUNCTION_TMPL_ARGScout<<"__STL_NULL_TMPL_ARGS <>"<<endl;
# elsecout<<"__STL_NULL_TMPL_ARGS"<<endl;
# endif# ifdef __STL_CLASS_PARTIAL_SPECIALIZATIONcout<<"__STL_TEMPLATE_NULL template<>"<<endl;
# elsecout<<"__STL_TEMPLATE_NULL"<<endl;
# endif// __STL_NO_NAMESPACES is a hook so that users can disable namespaces
// without having to edit library headers.
# if defined(__STL_USE_NAMESPACES) && !defined(__STL_NO_NAMESPACES)cout<<"__STL_USE_NAMESPACES begin"<<endl;cout<<"__STD std"<<endl;cout<<"__STL_BEGIN_NAMESPACE namespace std {"<<endl;cout<<"__STL_END_NAMESPACE }"<<endl;cout<<"__STL_USE_NAMESPACE_FOR_RELOPS"<<endl;cout<<"__STL_BEGIN_RELOPS_NAMESPACE namespace std {"<<endl;cout<<"__STL_END_RELOPS_NAMESPACE }"<<endl;cout<<"__STD_RELOPS std"<<endl;cout<<"__STL_USE_NAMESPACES end"<<endl<<endl;
# elsecout<<"! __STL_USE_NAMESPACES begin"<<endl;cout<<"__STD "<<endl;cout<<"__STL_BEGIN_NAMESPACE "<<endl;cout<<"__STL_END_NAMESPACE "<<endl;cout<<"__STL_USE_NAMESPACE_FOR_RELOPS"<<endl;cout<<"__STL_BEGIN_RELOPS_NAMESPACE "<<endl;cout<<"__STL_END_RELOPS_NAMESPACE "<<endl;cout<<"__STD_RELOPS "<<endl;cout<<"! __STL_USE_NAMESPACES end"<<endl<<endl;
# endif# ifdef __STL_USE_EXCEPTIONScout<<"__STL_USE_EXCEPTIONS begin"<<endl;cout<<"__STL_TRY try"<<endl;cout<<"__STL_CATCH_ALL catch(...)"<<endl;cout<<"__STL_RETHROW throw"<<endl;cout<<"__STL_NOTHROW throw()"<<endl;cout<<"__STL_UNWIND(action) catch(...) { action; throw; }"<<endl;cout<<"__STL_USE_EXCEPTIONS end"<<endl<<endl;
# elsecout<<"! __STL_USE_EXCEPTIONS begin"<<endl;cout<<"__STL_TRY "<<endl;cout<<"__STL_CATCH_ALL if (false)"<<endl;cout<<"__STL_RETHROW "<<endl;cout<<"__STL_NOTHROW "<<endl;cout<<"__STL_UNWIND(action) "<<endl;cout<<"! __STL_USE_EXCEPTIONS end"<<endl<<endl;
# endif#ifdef __STL_ASSERTIONS
# include <stdio.h>cout<<"__stl_assert(expr) \if (!(expr)) { fprintf(stderr, \"%s:%d STL assertion failure: %s\n\", \__FILE__, __LINE__, # expr); abort(); }"<<endl;
#elsecout<<"__stl_assert(expr)"<<endl;
#endif}int main(void)
{test();return 0;
}

运行结果:

[root@localhost stlsource]# g++ -o lconfig1 lconfig1.cpp
[root@localhost stlsource]# ./lconfig1
__GNUC__ begin
__STL_CLASS_PARTIAL_SPECIALIZATION
__STL_FUNCTION_TMPL_PARTIAL_ORDER
__STL_EXPLICIT_FUNCTION_TMPL_ARGS
__STL_MEMBER_TEMPLATES
__STL_PTHREADS
__STL_USE_EXCEPTIONS
__GNUC__ end__STL_NULL_TMPL_ARGS
__STL_TEMPLATE_NULL
! __STL_USE_NAMESPACES begin
__STD
__STL_BEGIN_NAMESPACE
__STL_END_NAMESPACE
__STL_USE_NAMESPACE_FOR_RELOPS
__STL_BEGIN_RELOPS_NAMESPACE
__STL_END_RELOPS_NAMESPACE
__STD_RELOPS
! __STL_USE_NAMESPACES end! __STL_USE_EXCEPTIONS begin
__STL_TRY
__STL_CATCH_ALL if (false)
__STL_RETHROW
__STL_NOTHROW
__STL_UNWIND(action)
! __STL_USE_EXCEPTIONS end__stl_assert(expr)

1.2)通过以上的测试,可以得到在linux平台下,stl_config.h 的实现定义如下:
        为了缩小篇幅,把相关的版权信息的屏蔽了。

#ifndef __STL_CONFIG_H
# define __STL_CONFIG_H# ifdef __GNUC__
# include <_G_config.h>
# define __STL_CLASS_PARTIAL_SPECIALIZATION
# define __STL_FUNCTION_TMPL_PARTIAL_ORDER
# define __STL_EXPLICIT_FUNCTION_TMPL_ARGS
# define __STL_MEMBER_TEMPLATES
# define __STL_PTHREADS
# define __STL_USE_EXCEPTIONS
# endif# define __STL_NULL_TMPL_ARGS
# define __STL_TEMPLATE_NULL# define __STD
# define __STL_BEGIN_NAMESPACE
# define __STL_END_NAMESPACE
# undef __STL_USE_NAMESPACE_FOR_RELOPS
# define __STL_BEGIN_RELOPS_NAMESPACE
# define __STL_END_RELOPS_NAMESPACE
# define __STD_RELOPS # define __STL_TRY
# define __STL_CATCH_ALL if (false)
# define __STL_RETHROW
# define __STL_NOTHROW
# define __STL_UNWIND(action) # define __stl_assert(expr)#endif /* __STL_CONFIG_H */// Local Variables:
// mode:C++
// End:

2,对stl_config.h中的宏的详解
    2.1)__STL_STATIC_TEMPLATE_MEMBER_BUG

  1. 如果编译器不支持static members of template classes(模板类静态成员),
  2. //       则定义__STL_STATIC_TEMPLATE_MEMBER_BUG
#include<iostream>
using namespace std;template <typename T>
class testClass {
public:static int _data;
};
//只对成员实现特化,记得加上template<>
template<>
int testClass<int>::_data=1;template<>
int testClass<char>::_data=2;int main()
{cout<<testClass<int>::_data<<endl;cout<<testClass<char>::_data<<endl;testClass<int> Obji1,Obji2;testClass<char> Objc1,Objc2;cout<<Obji1._data<<endl;cout<<Obji2._data<<endl;cout<<Objc1._data<<endl;cout<<Objc2._data<<endl;Obji1._data=3;Objc1._data=4;cout<<Obji1._data<<endl;cout<<Obji2._data<<endl;cout<<Objc1._data<<endl;cout<<Objc2._data<<endl;
}

运行结果:

[root@localhost stlsource]# ./lconfig3
1
2
1
1
2
2
3
3
4
4

2.2)__STL_CLASS_PARTIAL_SPECIALIZATION

  1. 如果编译器支持partial specialization of class templates(局部特殊化的类模板),
  2. //       则定义__STL_CLASS_PARTIAL_SPECIALIZATION
  3. //       参考文献: http://msdn.microsoft.com/en-us/library/9w7t3kf1(v=VS.71).aspx
#include<iostream>
using namespace std;template <class I,class O>
struct testClass
{testClass() {cout<<"I,O"<<endl;}
};
//对类实现偏特化
template <class T>
struct testClass<T*,T*>
{testClass() {cout<<"T*,T*"<<endl;}
};
//对类实现偏特化
template<class T>
struct testClass<const T*,T*>
{testClass(){ cout<<"const T*,T*"<<endl;}
};int main()
{testClass<int,char> obj1;testClass<int*,int*> obj2;testClass<const int*,int*> obj3;
}

运行结果:

[root@localhost stlsource]# ./lconfig5
I,O
T*,T*
const T*,T*

2.3)__STL_FUNCTION_TMPL_PARTIAL_ORDER

  1. 如果编译器支持partial ordering of function templates(部分排序函数模板),
  2. //       则定义__STL_FUNCTION_TMPL_PARTIAL_ORDER
  3. //       参考资料: http://msdn.microsoft.com/zh-cn/library/zaycz069.aspx
#include<iostream>
using namespace std;class alloc{
};template <class T,class Alloc=alloc>
class vector{
public:void swap(vector<T,Alloc>&) {cout<<"swap()"<<endl;}
};
//本来是#ifdef__STL_FUNCION_TMPL_PARTIAL_ORDER,但是貌似不支持
#ifndef __STL_FUNCION_TMPL_PARTIAL_ORDER
template <class T,class Alloc>
inline void swap(vector<T,Alloc>& x,vector<T,Alloc>& y)
{x.swap(y);
}
#endif // __STL_FUNCION_TMPL_PARTIAL_ORDERint main()
{vector<int>x,y;swap(x,y);
}

运行结果:

[root@localhost stlsource]# ./lconfig6
swap()

2.4)__STL_EXPLICIT_FUNCTION_TMPL_ARGS 
        整个 SGI STL  内都没有用到此一常数定义

  1. 如果编译器支持calling a function template by providing its template
  2. //       arguments explicitly(显式指定调用模板函数的模板参数)

2.5)__STL_MEMBER_TEMPLATES 

  1. 如果编译器支持template members of classes(类模板成员),
  2. //       则定义__STL_MEMBER_TEMPLATES
#include<iostream>
#include<typeinfo>
using namespace std;class alloc{
};
//类模板
template <typename T,typename Alloc=alloc>
class vector{
public:typedef T value_type;typedef value_type* iterator;
//函数模板template <typename I>void insert(iterator position,I first,I last){cout<<"insert()"<<endl;cout<<typeid(I).name()<<endl;}
};int main()
{int ia[5]={0,1,2,3,4};vector<int> x;vector<int>::iterator ite;x.insert(ite,*ia,*(ia+5));
}

运行结果:

[root@localhost stlsource]# ./lconfig8
insert()
i

2.6)__STL_LIMITED_DEFAULT_TEMPLATES

  1. 如果编译器不能根据前一个模板参数设定后面的默认模板参数,
  2. //       则定义__STL_LIMITED_DEFAULT_TEMPLATES
#include<iostream>
#include<cstddef>
using namespace std;class alloc{};template <typename T,class Alloc=alloc,size_t Bufsiz=0>
class deque{
public:deque(){cout<<"deque"<<endl;}
};template <typename T,class Sequence=deque<T> >
class stack{
public:stack(){ cout<<"stack"<<endl;}
private:Sequence c;//调用deque的构造函数初始化
};int main()
{stack<int> x;
}

  运行结果:

[root@localhost stlsource]# ./lconfig10
deque
stack

      2.7)__STL_NON_TYPE_TMPL_PARAM_BUG 

  1. 如果编译器处理模板函数的non-type模板参数类型推断有困难,
  2. //       则定义__STL_NON_TYPE_TMPL_PARAM_BUG
#include<iostream>
#include<cstddef>
using namespace std;class alloc{};inline size_t __deque_buf_size(size_t n,size_t sz)
{return n!=0?n:(sz<512?size_t(512/sz):size_t(1));
}template <class T,class Ref,class Ptr,size_t Bufsiz>
struct __deque_iterator{typedef __deque_iterator<T,T&,T*,Bufsiz> iterator;typedef __deque_iterator<T,const T&,const T*,Bufsiz> const_iterator;static size_t buffer_size() {return __deque_buf_size(Bufsiz,sizeof(T));}
};template <class T,class Alloc=alloc,size_t Bufsiz=0>
class deque
{
public:typedef __deque_iterator<T,T&,T*,Bufsiz> iterator;
};int main()
{cout<<deque<int>::iterator::buffer_size()<<endl;cout<<deque<int,alloc,64>::iterator::buffer_size()<<endl;
}

  运行结果:

  

     2.8)__STL_NULL_TMPL_ARGS(bound friend template friend)

<stl_config.h>定义__STL_NULL_TMPL_ARGS如下:

#ifdef __STL_NULL_TMPL_ARGS
# define __STL_NULL_TMPL_ARGS <>
#else
# define __STL_NULL_TMPL_ARGS
#endif

  这个组态常量常常出现在类似这样的场合(class template的friend函数声明)。

// in <stl_stack.h>
template<class T,class Sequence=deque<T> >
class stack{friend bool operator==___STL_NULL_TMPL_ARGS(const stack &,const stack&);friend bool operator< __STL_NULL_TMPL_ARGS(const stack&,const stack&);...
};展开后就变成了:template<class T,class Sequence=deque<T> >
class stack{friend bool operator== <>(const stack &,const stack&);friend bool operator<  <>(const stack&,const stack&);...
};

  这种奇特的语法是为了实现所谓的 bound friend templates,也就是说class template的某个具现体(instantiation)与其friend function template的某个具现体有一对一的关系。下面是测试程序:

#include<iostream>
#include<cstddef>
using namespace std;class alloc{};template<class T,class Alloc=alloc,size_t BufSiz=0>
class deque
{
public:deque(){cout<<"deque"<<endl;}
};
//类模板与友元的一对一关系需要前置声明
template<class T,class Sequence>
class stack;template<class T,class Sequence>
bool operator==(const stack<T,Sequence>& x,const stack<T,Sequence>& y);template<class T,class Sequence>
bool operator<(const stack<T,Sequence>& x,const stack<T,Sequence>& y);template<class T,class Sequence=deque<T> >
class stack
{//friend bool operator==<T>(const stack<T>&,const stack<T>&);//friend bool operator< <T>(const stack<T>&,const stack<T>&);//下面的都是等价于上面的//friend bool operator== <T>(const stack&,const stack&);//friend bool operator< <T>(const stack&,const stack&);friend bool operator== <>(const stack&,const stack&);friend bool operator< <>(const stack&,const stack&);
public:stack(){cout<<"stack"<<endl;}
private:Sequence c;
};template<class T,class Sequence>
bool operator==(const stack<T,Sequence> &x,const stack<T,Sequence> &y)
{return cout<<"operator=="<<'\t';
}template<class T,class Sequence>
bool operator<(const stack<T,Sequence> &x,const stack<T,Sequence> &y)
{return cout<<"operator<"<<'\t';
}int main()
{stack<int> x;stack<int> y;cout<<(x==y)<<endl;cout<<(x<y)<<endl;stack<char> y1;
//    cout<<(x==y1)<<endl;//   cout<<(x<y1)<<endl;
}

  运行结果:

2.9)__STL_TEMPLATE_NULL(class template explicit specialization)


<stl_config.h>定义了一个__STL_TEMPLATE_NULL如下:

#ifdef __STL_CLASS_PAPTIAL_SPECIALIZATION
#define __STL_TEMPLATE_NULL template<>
#else
#define __STL_TEMPLATE_NULL
#endif

  这个组态常量常常出现在类似这样的场合:

//in <type_traits.h>
template <class type> struct  _type_traits {...};
__STL_TEMPLATE_NULL struct _type_traits<char> {};//in <stl_hash_fun.h>
template <class key> struct hash{};
__STL_TEMPLATE_NULL struct hash<char> {};
__STL_TEMPLATE_NULL struct hash<unsigned char> {};

  展开后:

//in <type_traits.h>
template <class type> struct  _type_traits {...};
template<> struct _type_traits<char> {};//in <stl_hash_fun.h>
template <class key> struct hash{};
template<> struct hash<char> {};
template<> struct hash<unsigned char> {};

  这就是所谓的class template explicit specialization。

下面是一个测试程序:

#include<iostream>
//不能使用 using namespace std 这会将标准库中的hash引入,然后通不过
using std::cout;
using std::endl;//貌似我使用g++编译,定义为空不能通过
//#define __STL_TEMPLATE_NULL
#define __STL_TEMPLATE_NULL template<>template <class key>
struct hash
{//重载函数调用运算符void operator()(){cout<<"hash<T>"<<endl;}
};template<>
struct hash<char>
{void operator()(){cout<<"hash<char>"<<endl;}
};__STL_TEMPLATE_NULL
struct hash<unsigned char>
{void operator()(){cout<<"hash<unsigned char"<<endl;}
};int main()
{hash<long> t1;hash<char> t2;hash<unsigned char> t3;t1();//函数对象和函数指针类似,可以作为可调用对象t2();t3();
}

  运行结果:

STL源码剖析—stl_config相关推荐

  1. STL源码剖析 stack 栈 概述->(使用deque双端队列 / list链表)作为stack的底层容器

    Stack是一种先进后出的数据结构,他只有一个出口 stack允许 新增元素.移除元素.取得最顶端的元素,但是无法获得stack的内部数据,因此satck没有遍历行为 Stack定义的完整列表 (双端 ...

  2. STL源码剖析 __type_traits

    traits编程 弥补了C++本身的不足 STL只对迭代器进行规范制定出了iterator_traits,SGI在此基础上进一步扩展,产生了__type_traits 双下划线的含义是这个是SGI内部 ...

  3. STL(C++标准库,体系结构及其内核分析)(STL源码剖析)(更新完毕)

    文章目录 介绍 Level 0:使用C++标准库 0 STL六大部件 0.1 六大部件之间的关系 0.2 复杂度 0.3 容器是前闭后开(左闭右开)区间 1 容器的结构与分类 1.1 使用容器Arra ...

  4. STL源码剖析学习七:stack和queue

    STL源码剖析学习七:stack和queue stack是一种先进后出的数据结构,只有一个出口. 允许新增.删除.获取最顶端的元素,没有任何办法可以存取其他元素,不允许有遍历行为. 缺省情况下用deq ...

  5. 《STL源码剖析》学习-- 1.9-- 可能令你困惑的C++语法1

    最近在看侯捷的<STL源码剖析>,虽然感觉自己c++看得比较深一点,还是感觉还多东西不是那么明白,这里将一些细小的东西或者概念记录一下. 有些东西是根据<C++编程思想>理解的 ...

  6. 《STL源码剖析》学习--6章--_rotate算法分析

     最近在看侯捷的<STL源码剖析>,其中有许多不太明白之处,后经分析或查找资料有了些理解,现记录一下. <STL源码剖析>学习--6章--random access ite ...

  7. 《STL源码剖析》学习--6章--power算法分析

    最近在看侯捷的<STL源码剖析>,其中有许多不太明白之处,后经分析或查找资料有了些理解,现记录一下. 6章--power算法分析 书本中的算法如下所示: template <clas ...

  8. STL源码剖析——P142关于list::sort函数

    在list容器中,由于容器自身组织数据的特殊性,所以list提供了自己的排序函数list::sort, 并且实现得相当巧妙,不过<STL源码剖析>的原文中,我有些许疑问,对于该排序算法,侯 ...

  9. STL源码剖析---红黑树原理详解下

    转载请标明出处,原文地址:http://blog.csdn.net/hackbuteer1/article/details/7760584       算法导论书上给出的红黑树的性质如下,跟STL源码 ...

最新文章

  1. 手机触屏滑动图片切换插件swiper.js
  2. 时序预测竞赛之异常检测算法综述
  3. DNS解析过程详解【转】
  4. Nature:拟南芥微生物组功能研究0概述
  5. java端模拟http的get、post请求(转)
  6. js,jquery获取页面元素距离浏览器工作区顶端的距离
  7. 数学--数论--HDU-2698 Maximum Multiple(规律)
  8. 通过图书编号查询python_Python图书接口调用代码实例
  9. potplayer 多个进程_什么是进程
  10. 【Loss】深度学习的多个loss如何平衡?
  11. mysql基础之mariadb对表中数据的增删改查
  12. CGLIB实现AOP,MethodInterceptor接口和Enhancer详解——Spring AOP(四)
  13. Makefile教程(这一篇足够从入门到放弃!!!)
  14. 软件工程的完整生命周期
  15. 共探数字化安全新未来,CSA SDP2.0标准发布暨零信任技术研讨会召开
  16. cocos2d-x游戏开发 《坠入蔚蓝》
  17. 使用XINCheck文档查重软件对本地文档查重
  18. vue v-for循环改变循环数据视图不更新
  19. c语言四则运算报告,C语言四则运算实验报告.doc
  20. mathcad使用说明

热门文章

  1. 安卓Queue的使用
  2. 大数据量生成工具源代码(Delphi)
  3. ASP.NET MVC增删改查
  4. 进入DRF和ANGULAR的整合学习,这三篇入门内容一定要学好的
  5. nagios监控单网卡双IP
  6. Solr Facet 查询
  7. js函数的内部属性---arguments,callee,caller
  8. firefox 4b7截图
  9. 几种身份的创业者优劣势大比拼
  10. [读书笔记]My Life--Bill Clinton