C++ 实现 STL 标准库和算法*
template 编程*
本节内容主要讲述 C++11 模板的用法,同时简单讲解迭代器的相关知识,为后面的容器和算法的内容作铺垫。
基本语法*
模板编程是 STL 的基石,也是 C++11 的核心特性之一。模板的基本语法如下:
template <typename/class T>
T 叫做模板形参,一旦模板被实例化,T 也会变成具体的类型。
模板函数*
template <typename T>
T add(const T lva ,const T rva)
{
T a ;
a = lva + rva;
return a;
}
以上是一个模板函数的简单示例,template 关键字告知编译器模板和参数必要信息。函数模板支持默认参数,顺序任意。在此例中需要两个参数的类型一致。可以添加模板类型参数实现不同类型相加。
类模板和成员模板*
类模板*
C++11 不仅支持对函数的模板化,也支持对类的模板:
template <class T>
class Myclass
{
T a;
public:
T add(const T lva ,const T rva);
};
template <class T>
T Myclass<T>::add(const T lva, const T rva)
{
a = lva + rva;
return a;
}
实例化类时需要指定类型模板参数,类模板也支持默认参数。但必须严格从右往左默认化。
成员模板*
class, struct, template class 的成员也可以使用模板。
template <class T>
class Myclass
{
public:
T a;
template <typename type_1 , typename type_2>
type_1 add(const type_1 lva ,const type_2 rva);
};
template <class T>
template <typename type_1,typename type_2>
type_1 Myclass<T>::add(const type_1 lva, const type_2 rva)
{
a = lva + rva;
return a;
}
类的声明中使用了一个嵌套的模板声明,且通过作用域运算符 :: 指出 add() 是类的成员,需要注意的一点,有些编译器不支持模板成员,有些编译器不支持在类外定义。甚至允许在模板类中再建立模板类:
template <class T>
class Myclass
{
public:
T a;
template <typename type_1 , typename type_2>
type_1 add(const type_1 lva ,const type_2 rva);
template <class type_3>
class Myclass_2; // 声明放在这里,具体定义放在类外进行。
Myclass_2<T> C; // 定义一个Myclass_2 类 A。使用 T 进行实例化
};
template <class T>
template <typename type_1,typename type_2>
type_1 Myclass<T>::add(const type_1 lva, const type_2 rva)
{
a = lva + rva;
return a;
}
template <class T>
template <class type_3>
class Myclass<T>::Myclass_2
{
public:
type_3 value;
type_3 sub(const type_3 a , const type_3 b) {vlaue = a - b;}
};
模板里中的静态成员*
类的静态成员是存储在静态区的,被所有类对象共享,模板类中的静态成员也不会被复制多份,而是被同类实例化的类对象共享,比如所有 int 和所有 double 的类对象,享有相互独立的静态变量。
typename 和 class*
模板中常用的两个关键词,在模板定义的时候没有什么区别。
class Myclass{
public:
Myclass();
typedef int test; //定义类型别名
}
template <class T>
class Myclass2{
public:
Myclass2();
T::test *a // 声明一个指向T::test类型的指针。
// typename T::test * a
}
C++ 中允许在类中定义类型别名,且使用时和类访问类成员的方法一样。编译器在编译时产生二义性,它根本不知道这是一个类型还是别名,就需要加上 typename 显式说明。
迭代器*
本节主要介绍 5 种常见的迭代器:输入、输出迭代器,前向逆向迭代器,双向迭代器和随机迭代器。主要内容包括各自的构造方法和操作方法。
迭代器详述*
迭代器 iterator 是一种对象,它能够用来遍历标准模板库容器中的部分或全部元素,每个迭代器对象代表容器中的确定的地址。迭代器修改了常规指针的接口,所谓迭代器是一种概念上的抽象:行为上像迭代器的东西都可以叫做迭代器。然而迭代器有很多不同的能力,它可以把抽象容器和通用算法有机地统一起来。
简单概括:迭代器是一种检查容器内元素并遍历元素的可带泛型数据类型。
输入迭代器*
通过对输入迭代器解除引用,它将引用对象,而对象可能位于集合中。通常用于传递地址。
template<class T, class Distance>
struct input_iterator {
typedef input_iterator_tag iterator_category;//返回类型
typedef T value_type;//所指对象类型
typedef Distance difference_type;//迭代器间距离类型
typedef T* pointer;//操作结果类型
typedef T& reference;//解引用操作结果类型
};
输出迭代器*
与输入迭代器相似,也只能单步向前迭代元素,不同的是该类迭代器对元素只有写的权限。通常用于返回地址。
struct output_iterator{
typedef output_iterator_tag iterator_category;
typedef void value_type;
typedef void difference_type;
typedef void pointer;
typedef void reference;
};
前向迭代器*
前向迭代器可以在一个正确的区间中进行读写操作,它拥有输入迭代器的所有特性,和输出迭代器的部分特性,以及单步向前迭代元素的能力。通常用于遍历。
template <class T, class Distance> struct forward_iterator{
typedef forward_iterator_tag iterator_category;
typedef T value_type;
typedef Distance difference_type;
typedef T* pointer;
typedef T& reference;
};
双向迭代器*
在前向迭代器的基础上提供了单步向后迭代的能力。
template <class T, class Distance> struct bidirectional_iterator{
typedef bidirectional_iterator_tag iterator_category;
typedef T value_type;
typedef Distance difference_type;
typedef T* pointer;
typedef T& reference;
};
随机迭代器*
该类迭代器能完成上面所有迭代器的工作,它自己独有的特性就是可以像指针那样进行算术计算,而不是仅仅只有单步向前或向后迭代。
template <class T, class Distance> struct random_access_iterator{
typedef random_access_iterator_tag iterator_category;
typedef T value_type;
typedef Distance difference_type;
typedef T* pointer;
typedef T& reference;
};
迭代器辅助函数*
advance:用于迭代器前移,增加迭代的位置。可用于定向访问到迭代器的某个变量