容器
容器(Container) | 分类 |
---|---|
顺序容器(序列容器)Sequence Container | vector,list,deque |
关联容器 Associative Container | map,set |
容器适配器 Container Adapter | stack,queue,priority_queue |
一.顺序容器(序列容器)Sequence Container
vector
vector的四种迭代器:
迭代器 | 作用 |
---|---|
iterator | 可修改迭代器 begin() end() |
reverse_iterator | 逆序可修改迭代器 rbegin() rend() |
const_iterator | 不可修改迭代器 cbegin() cend() |
const_reverse_iterator | 逆序不可修改迭代器 crbegin() crend() |
vector迭代器的使用:
#include <iostream>
#include <vector>
using namespace std;
void Travesal(const vector<int>& vec){ //定义外部函数用正序迭代器遍历vector
vector<int>::const_iterator it = vec.cbegin();
while(it != vec.cend()){
cout << *it << " ";
++it;
}
cout << endl;
}
void TravesalReverse(const vector<int>& vec){ //定义外部函数用逆序迭代器遍历vector
vector<int>::const_reverse_iterator rit = vec.crbegin();
while(rit != vec.crend()){
cout << *rit << " ";
++rit;
}
cout << endl;
}
void Travesal2(const vector<int>& vec){ //用自适应变量遍历数组,c++11特有
for(auto& n:vec){ //若要修改里面元素时,auto必须要用引用类型才能修改本身
cout << n << " "; //否则n取的只是vector的副本
}
cout << endl;
}
vector<int>& Multipy(vector<int>& vec,int n){ //遍历并整体乘n
vector<int>::iterator it = vec.begin();
while(it != vec.end()){
*it = *it*n;
++it;
}
return vec;
}
vector<int>& Multipy2(vector<int>& vec,int m){ //遍历并整体乘m,用自适应变量for循环实现
for(auto n:vec){
n = n*m;
}
return vec;
}
int main(){
vector<int> vec={1,2,3,4,5,6,7};
for(int i=0;i!=vec.size();i++){
cout << vec[i] << " ";
}
cout << endl;
vector<int>::iterator it = vec.begin(); //正序迭代器
while(it != vec.end()){
cout << *it << " ";
++it;
}
cout << endl;
vector<int>::reverse_iterator rit = vec.rbegin(); //逆序迭代器
while(rit != vec.rend()){
cout << *rit << " ";
++rit;
}
cout << endl;
for(auto n:vec){ //自适应变量遍历
cout << n << " ";
}
cout << endl;
Travesal(vec); //调用外部定义的函数
TravesalReverse(vec);
Travesal2(vec);
Travesal(Multipy(vec,100));
Travesal(Multipy2(vec,100));
}
运行结果:
注意:用自适应变量遍历容器时,若要修改容器里的元素,auto必须要用引用类型才能修改本身,否则n只是取的只是vector副本,正常遍历则不用引用类型也可以。
修改vector空间与容量:
#include <iostream>
#include <vector>
using namespace std;
int main(){
vector<int> vec={1,2,3,4,5,6,7};
cout << vec.size() << "," << vec.capacity() <<endl;
vec.resize(10); //修改size
// vec.reserve(5); //修改capacity
cout << vec.size() << "," << vec.capacity() <<endl;
vec.resize(5);
// vec.reserve(6);
cout << vec.size() << "," << vec.capacity() <<endl;
}
vector其他的具体操作可以参考链接
实现vector和迭代器iterator:
特殊情况看如何重载后缀++(与前缀++做对比)
#include <iostream>
#include <string>
using namespace std;
template<typename T>
class vector{
T* _data; //下划线表示私有成员变量
size_t _size; //元素个数
size_t _capacity; //容量
public: //size_t可以提高代码的可移植性,是long的重载,所占字节大小由主机位数所决定
vector():_data(NULL),_size(0),_capacity(0){}
void push_back(const T& val){
++_size;
if(NULL == _data){
++_capacity;
_data = new T[_capacity];
}
else{
if(_size>_capacity){ //如果元素数量大于容量,进行扩容
_capacity*=2;
T* temp = new T[_capacity];
for(int i=0;i<_size-1;++i){
temp[i] = _data[i];
}
delete [] _data;
_data = temp;
}
}
_data[_size-1] = val;
}
int size()const{ return _size;}
int capacity()const{return _capacity;}
T& operator[](int index){
return _data[index];
}
//qie tao lei :lei zhong ding yi de lei
class iterator{
T* _p;
public:
iterator(T* p):_p(p){};
T& operator*(){ return *_p;}
T* operator->(){ return _p;}
iterator operator++(){
++_p;
return *this;
}
bool operator==(const iterator& it)const{
return _p == it._p;
}
bool operator!=(const iterator& it)const{ //只有上面的双等号重载过后==才可以引用
return !(*this == it); //==才可以引用
// return _p != it._p; //等价于
}
iterator operator+(int n)const{
return iterator(_p+n);
}
iterator operator-(int n)const{
return iterator(_p-n);
}
iterator operator++()const{ //前缀++运算符重载
return iterator(++_p);
}
iterator operator++(int)const{ //后缀++运算符重载,int相当于占位符
iterator tmp(_p); //创建一个临时对象用来返回
++_p;
return tmp;
}
iterator operator--()const{
return iterator(--_p);
}
iterator operator--(int)const{
iterator tmp(_p);
--_p;
return tmp
}
};
iterator begin(){
return iterator(_data); //本质就是实例化一个迭代器对象,对象里包含着元素的地址
} //并将这个元素的地址传出去
iterator end(){
return iterator(_data+_size);
}
};
class Student{ //定义一个学生类进行测试
public:
string name;
int age;
};
int main(){
vector<int> vec;
for (int i = 0; i < 20; ++i) {
vec.push_back(i);
cout << "size:" << vec.size() << ",capcity:" << vec.capacity() << endl;
}
for (int j = 0; j < vec.size(); ++j) {
cout << vec[j] << " ";
}
cout << endl;
vector<int>::iterator it = vec.begin();
while(it != vec.end()){
cout << *it << endl;
++it; //重载的是前加 ,这里的本质是重载对象的成员函数
} //而对象本身不能自加
cout << endl;
for(auto n:vec){
cout << n << " ";
}
cout << endl;
vector<Student> vec1; //注意这里的定义的模板的类类型如何初始化定义
vec1.push_back({"zhangsan",21}); //类似于初始化结构体
vec1.push_back({"lisi",23});
vec1.push_back({"wangwu",20});
vector<Student>::iterator it1 = vec1.begin();
while(it1 != vec1.end()){
cout << it1->name << "," << it1->age << endl; //调用符号 -> 的重载函数
++it1;
}
cout << endl;
}
list列表
list也有四种迭代器
迭代器 | 作用 |
---|---|
iterator | 可修改迭代器 begin() end() |
reverse_iterator | 逆序可修改迭代器 rbegin() rend() |
const_iterator | 不可修改迭代器 cbegin() cend() |
const_reverse_iterator | 逆序不可修改迭代器 crbegin() crend() |
list使用迭代器:
#include <iostream>
#include <list>
using namespace std;
void Travelsal(const list<int>& l){ //迭代器遍历list写在外部函数,使用不可修改迭代器
list<int>::const_iterator it = l.cbegin();//形参设置为常量引用,防止函数内部修改传对象
while(it != l.cend()){ //这样函数既可以接受常量对象也可以结束非常量对象
cout << *it << " ";
it++;
}
cout << endl;
}
void TravelsalReverse(const list<int>& l){
list<int>::const_reverse_iterator rit = l.crbegin();
while(rit != l.crend()){
cout << *rit << " ";
rit++;
}
cout << endl;
}
int main(){
list<int> l = {1,2,3,4,5};
for(auto n:l){
cout << n << " ";
}
cout << endl;
for(int i=0;i<l.size();i++){
// cout << l[i] << " "; //列表不接受下标访问
}
cout << endl;
list<int>::iterator it = l.begin(); //正序迭代器
while(it != l.end()){
cout << *it << " ";
++it;
}
cout << endl;
list<int>::reverse_iterator rit = l.rbegin(); //倒序迭代器
while(rit != l.rend()){
cout << *rit << " ";
rit++;
}
cout << endl;
Travelsal(l); //调用外部函数
TravelsalReverse(l);
}
运行结果:
list的增删改操作
添加list尾元素:
l.push_back(6);
l.push_back(7);
l.push_back(8);
Travelsal(l);
删除list尾元素:
l.pop_back();
l.pop_back();
l.pop_back();
添加list头元素(list特有):
l.push_front(-2);
l.push_front(-1);
l.push_front(0);
Travelsal(l);
删除list头元素(list特有):
l.pop_front();
l.pop_front();
l.pop_front();
在第二个位置上插入100:
it = l.begin();
// it = it+1 //list迭代器不能做算数运算,但是可以自加自减
++it; //因为对象it中运算符++重载过了
l.insert(it,100);
Travelsal(l);
删除100:(因为添加100后,it会指向100后的那个元素,所以要向前移动一位)
--it;
l.erase(it);
Travelsal(l);
批量添加:
it = l.begin();
++it;
l.insert(it,5,100);
批量删除:
list<int>::iterator first = l.begin();
++first;
l.erase(first,it);
Travelsal(l);
插入数组:(之所以插在第二元素开始的位置,是因为it之前所停留在那个位置)
int arr[] = {11,12,13,14};
l.insert(it,arr,arr+4);
Travelsal(l);
list中插入向量vec:
vector<int> vec = {21,22,23,24};
l.insert(l.end(),vec.begin(),vec.end());
Travelsal(l);
随机访问:
it = next(l.begin(),4);
*it = 10000;
Travelsal(l);
list特有成员函数:
倒序输出:
l.reverse();
Travelsal(l);
排序:
l.sort();
Travelsal(l);
指定值删除元素:
l.remove(10000);
Travelsal(l);
实现list和迭代器iterator:
#include <iostream>
#include <exception>
using namespace std;
namespace miniSTL{ //定义一个小型标准模板库的命名空间
template<typename T>
class list{
struct Node{ //list(链表)的节点存储结构为结构体
T val;
Node* prev;
Node* next;
Node(const T& val):val(val),prev(NULL),next(NULL){}
};
Node* head,*tail;
int _size;
public:
list():head(NULL),tail(NULL),_size(0){} //构造函数
~list(){ //析构函数
while(NULL != head){
Node* next = head->next;
delete head;
head = next;
}
void push_back(const T& val){
++_size;
Node* node = new Node(val);
if(NULL == head){
head = tail =node;
}
else{
tail->next = node;
tail = node;
}
}
int size(){
return _size;
}
T& operator[](int index){
int count = 0;
Node* p = head;
while(NULL != p){
if(count++ ==index) break;
p = p -> next;
}
return p->val;
}
class iterator{ //类中类,定义迭代器
Node* p;
public:
iterator(Node* p):p(p){};
T& operator*(){
return p->val;
}
T* operator->(){
return &(p->val)
}
iterator operator++(){
p=p->next;
return *this;
}
iterator operator++(int){ //运算符重载后缀++
iterator tmp(*this); //初始化一个临时对象
p=p->next;
return tmp;
}
iterator operator--(){
p=p->prev;
return *this;
}
iterator operator--(int){ //运算符重载后缀--
iterator tmp(*this); //初始化一个临时对象
p=p->prev;
return tmp;
}
bool operator==(const iterator &it)const{
return p == it.p;
}
bool operator!=(const iterator &it)const{
return p != it.p;
}
};
iterator begin(){return iterator(head);}
iterator end(){ return iterator(NULL);}
};
}
using namespace miniSTL;
int main(){
list<int> li;
li.push_back(1);
li.push_back(2);
li.push_back(3);
cout << li.size() << endl;
for (int i = 0; i < li.size(); ++i) {
cout << li[i] << endl;
}
list<int>::iterator it = li.begin(); //测试迭代器
while(it != li.end()){
cout << *it << endl;
++it;
}
for(auto n:li){ //测试++重载
cout << n << endl; //因为只有重载++实现后,自适应变量循环才可以使用
}
}
关于vector和list的构造函数定义
#include <iostream>
#include <vector>
using namespace std;
void Print(const vector<int>& vec){
for(auto n:vec){
cout << n << " ";
}
cout << endl;
}
int main() {
vector<int> empty; //默认构造空容器
Print(empty);
vector<int> fault(10); //初始化为10个0元素
Print(fault);
vector<int> fault2(10, 2); //初始化为10个2元素
Print(fault2);
vector<int> vec = {1, 2, 3, 4, 5, 6, 7, 8, 9}; //显式初始化
vector<int> vec1 = vec; //拷贝构造函数
Print(vec1);
vector<int> vec2(vec.begin(), next(vec.begin(), 6)); //部分构造
Print(vec2);
vec2 = vec1; //赋值
Print(vec2);
vec2 = {10, 11, 12, 13, 14};
Print(vec2);
vec2.assign(next(vec1.begin(), 6), vec1.end());
Print(vec2);
}
对于list和vector有相同的构造函数
emplace_back可以直接使用构造函数的参数,在函数内部执行对象的构造:
二.关联容器 Associative Container
set(集合)
示例:
#include <iostream>
#include <set>
using namespace std;
void Print(const set<int>& s){
for(auto n:s){
cout << n << " ";
}
cout << endl;
}
int main(){
set<int> s = {10,2,2,2,13,4,15,6};
Print(s);
s.insert(-1);
Print(s);
s.insert(-1); //验证值唯一,只能插入一个-1
s.insert(-1);
Print(s);
auto it = s.rbegin();
while(it != s.rend()){ //倒序输出
cout << *(it++) << ",";
}
cout << endl;
cout << s.size() << endl;
s.erase(-1);
Print(s);
}
统计集合中元素个数:
cout << s.count(3) << endl;
cout << s.count(4) << endl;
查找集合中指定元素:
auto it3 = s.find(3);
cout << (it3 == s.end()) << endl;
auto it4 = s.find(4);
cout << *it4 <<endl;
// *it4 = 100; 禁止修改
set存放的对象必须可以比较大小,所以类必须重载:
class Simple{
public:
bool operator==(const Simple&)const{
return true;
}
bool operator<(const Simple&)const{
return true;
}
};
int main(){
set<Simple> ss;
}
集合元素之间实现排序:
#include <set>
#include <vector>
#include <iostream>
#include <string>
using namespace std;
template <class T>
void Print(const T& s){ //定义一个打印的模板函数
for(auto n:s){
cout << n << " ";
}
cout << endl;
}
class Greator{ //定义一个普通整型集合排序的类,返回值为布尔型决定两元素之间需不需要交换位置
public:
bool operator()(int a,int b){
return a > b;
}
};
class Student{
string name;
int age;
float scores;
public:
Student(const string& name,int age,float scores):name(name),age(age),scores(scores){}
int GetAge()const{return age;}
float GetScores()const{return scores;}
friend ostream& operator<<(ostream& os,const Student& s){
return os << s.name << ',' << s.age << ',' << s.scores;
}
};
class AgeCom{ //定义按年龄排序的仿函数类,返回值为布尔型决定两元素之间需不需要交换位置
public:
bool operator()(const Student& a,const Student& b){
return a.GetAge() > b.GetAge();
}
};
class ScoreComp{ //定义按分数排序的仿函数类,返回值为布尔型决定两元素之间需不需要交换位置
public:
bool operator()(const Student& a,const Student& b){
return a.GetScores() > b.GetScores();
}
};
int main() {
set<int, Greator> s;
s = {10,2,2,2,13,4,15,6};
Print(s);
set<Student,AgeCom> stu = {
Student("zhangsan",21,89),
Student("lisi",19,78),
Student("wangwu",20,69)
};
Print(stu);
set<Student,ScoreComp> stu2(stu.begin(),stu.end());
Print(stu2);
}
复习函数指针:
项目 | 核心思想 |
---|---|
C语言 | 面向过程编程 |
函数指针 | 函数式编程 |
c++语言 | 面向对象编程 |
模板 | 泛型编程 |
#include <iostream>
#include <vector>
using namespace std;
void Display(int& n){
cout << n << " ";
}
void Double(int& n){
n*=n;
}
typedef void (*func_t)(int& n); //定义一个返回类型为空,参数列表为整型引用的函数指针func_t
void Travesal(vector<int>& vec,func_t func){
for(auto& n:vec){
func(n);
}
}
int main(){
vector<int> vec = {1,2,3,4,5,6};
Travesal(vec,Display);
cout << endl;
Travesal(vec,Double);
Travesal(vec,Display);
cout << endl;
}
模板替换函数指针
#include <iostream>
#include <vector>
#include <list>
#include <set>
using namespace std;
template <typename T>
void Display(T& n){
cout << n << " ";
}
//void Double(int& n){
// n*=n;
//}
//typedef void (*func_t)(int& n); //这里应用了模板自动推导类型,已经用不到函数指针了
template <typename T,typename F> //这里属于自动推导参数类型
void Travesal(T& vec,F func){
for(auto n:vec){
func(n);
}
}
int main(){
vector<int> vec = {1,2,3,4,5,6};
Travesal(vec,Display<int>); //参数只传个函数名即可,真正的调用在函数内部
cout << endl;
// Travesal(vec,Double);
Travesal(vec,Display<int>);
cout << endl;
vector<float> vec2 = {1,1,2,2,3,3,4,4,5,5,6,6};
Travesal(vec2,Display<float>);
list<int> li = {1,2,3,4,5,6};
Travesal(vec2,Display<float>);
cout << endl;
set<int> s = {1,2,3,4,5,6};
Travesal(s,Display<int>);
cout << endl;
}
仿函数的应用:
#include <iostream>
#include <vector>
#include <list>
#include <set>
using namespace std;
template <typename T>
void Display(T& n){
cout << n << " ";
}
template<typename T> //定义一个仿函数模板类
class CDisplay{ //类中只有一个()运算符重载函数
public:
void operator()(T& n)const{
cout << n << " ";
}
};
template <typename T,typename F> //定义的函数模板,传入参数时自动推导类型
void Travesal(T& vec,F func){
for(auto n:vec){
func(n);
}
}
int main(){
vector<int> vec = {1,2,3,4,5,6};
Travesal(vec,Display<int>);
cout << endl;
Travesal(vec,Display<int>);
cout << endl;
vector<float> vec2 = {1,1,2,2,3,3,4,4,5,5,6,6};
Travesal(vec2,Display<float>);
list<int> li = {1,2,3,4,5,6};
Travesal(vec2,Display<float>);
cout << endl;
set<int> s = {1,2,3,4,5,6};
Travesal(s,Display<int>);
cout << endl;
int n = 100;
Display(n);
CDisplay<int> display;
display(n); //一般的仿函数:类名+()重载函数
CDisplay<int>()(n); //CDisplay()(n),CDdisply()属于类名,(n)调用的是运算符
//重载成员函数,这个类是匿名构造的
Travesal(s,display);
Travesal(s,CDisplay<int>()); //这里只是属于构造一个匿名对象,在Travesal函
//数内部定义了func(n),从而实现仿函数CDisplay<int>()(n)的调用
Travesal(s,[](int n){cout << n << ',';});
}
说明一:
template <typename T,typename F>
void Travesal(T& vec,F func)
定义的是模板函数,调用函数Travesal时,传入两个参数,会根据参数的类型进行自动推导
说明二:
如果F func传入的是一般函数的函数名,推导的就是指针类型,因为函数名代表的是函数的首地址
说明三:
CDisplay<int display;
display(n);
这里最经典的仿函数,实例化一个对象,对象调用()运算符重载的成员函数,外形像一个函数,实际不是,它等价于display.operator()(n);而display(n)只是它的简写形式
说明四:
Travesal(s,display);
这里的display传入的不是函数名,而是对象名,所以编译器会自动推导为CDisplay类,而在Travesal函数中的func(n)会自动转换成为仿函数调用,因为display()的()在类中重载过了,这和一般函数名做参数有本质的区别
说明五:
CDisplay<int()(n);
这里的CDisplay构造了一个匿名对象,然后再调用()的运算符重载成员函数,也属于仿函数的调用
说明六:
Travesal(s,CDisplay());
这里传入的是一个这里的CDisplay构造的一个匿名对象,然后经过Travesal函数内部func(n),相当于匿名对象的仿函数CDisplay<int()(n),它等价于CDisplay<int()operator()(n);
说明七:
[](int n){cout << n << ‘,’;
这里是Lambada表达式
map(映射关系)
#include <map>
#include <iostream>
#include <string>
using namespace std;
int main(){
map<string,string> dict = { //键值对存储形式
{"Apple","pinguo"},
{"Orange","juzi"},
{"Banana","xiangjiao"}
};
cout << dict["Apple"] << endl; //只能通过前面查找后面,反之不可以
if(dict.count("xiangjiao") == 1){
cout << dict["xiangjiao"] << endl; //如果查询不到,则创建一个新的键值对
}
for(auto p :dict){
cout << p.first << "," << p.second << endl; //循环遍历输出
}
}
map修改:
dict["Orange"] = "chengzi";
for(auto p :dict){
cout << p.first << "," << p.second << endl;
}
map插入:
dict.insert(pair<string,string>("cherry","yintao")); //插入函数(手动输入类型)
dict.insert(make_pair("cherries","chelizi")); //插入模板函数(自动推导)
dict.insert(pair<string,string>("cherry","yintao2")); //插入相同的键值无效,并不会增加新的元素
键值对pair的存储结构本质为结构体模板:
template<typename T,typename S>
struct pair{
T first;
S second;
};
map按键查找:
map<string,string>::iterator it = dict.find("banana");
if(it != dict.end()){
cout << it ->first << " " << it->second << endl;
}
map按键删除:
dict.erase("Apple");
for(auto p :dict){
cout << p.first << "," << p.second << endl;
}
map中元素的顺序并不是按照插入的顺序排列的,而是map结构有一套自己的排序算法
三.容器适配器 Container Adapter
stack(栈)
示例代码:
#include <iostream>
#include <stack>
#include <vector>
using namespace std;
int main(){
stack<int> s;
for (int i = 0; i < 10; ++i) {
s.push(i);
}
cout << "size" << s.size() <<endl;
while(!s.empty()){
cout << s.top() << endl;
}
//不可以使用迭代器
//不能随机访问[]
//不能使用for(auto n:s)
//将vector转成stack
vector<int> vec = {1,2,3,4,5};
stack<int,vector<int>> s1(vec);
vector<int> res;
while(!s1.empty()){
res.push_back(!s1.empty());
s1.top();
}
for(auto m:res){
cout << m << " ";
}
cout << endl;
}
模板函数中使用静态变量和嵌套类中变量的特殊情况:
typename的第二种用法
#include <iostream>
using namespace std;
class Simple{
public:
static int Static;
class Test{};
typedef int Number;
};
int Simple::Static = 0; //类中的静态成员变量要在类外定义
template <typename T>
void Func(T& s){
T::Static; //模板认为类名(T::XXXX)只是在访问类的静态成员变量,而不是使用嵌套类定义的对象
typename T::Test n; //如果在模板中使用类里面定义的类型,必须在前面加上关键字typename
typename T::Test num; //这是typename的第二个作用,第一个作用是在声明模板的类型时使用
}
int main(){
Simple::Static;
Simple::Test n;//在非模板里面可以直接使用,不需要加上关键字typename
//类里面的静态成员变量和类内部类型的访问方式是一样的,类名::XXXX
Simple::Number num;
Simple s;
Func(s);
}
模板函数迭代器的统一以及获取首尾元素的模板函数
#include <iostream>
#include <vector>
#include <list>
#include <set>
#include <algorithm>
using namespace std;
namespace MiniSTL{
//模板函数迭代器的统一
template <typename T>
typename T::iterator begin(T& c){ //iterator是T类中的嵌套类,所以在实例化它的时候
return c.begin(); //要用关键字typename声明,告诉编译器T::iterator
} //是一个类型,而不是在初始化静态变量
template <typename T>
typename T::iterator end(T& c){
return c.end();
}
template <typename T,size_t N> //偏特化
T* begin(T (&arr)[N]){
return arr;
}
template <typename T,size_t N> //偏特化
T* end(T (&arr)[N]){
return arr+N;
}
//获取首尾元素的模板函数
template <typename T>
typename T::value_type front(T& c){
return *c.begin();
}
template <typename T>
typename T::value_type back(T& c){
typename T::iterator e = c.end();
--e;
return *e;
}
template <typename T,size_t N>
T front(T (&arr)[N]){
return arr[0];
}
template <typename T,size_t N>
T back(T (&arr)[N]){
return arr[N-1];
}
}
int main(){
vector<int> vec = {1,2,3,4,5}; //定义vector
for_each(vec.begin(),vec.end(),[](int n){cout << n << " ";});
cout << endl;
set<int> s = {1,2,3,4,5}; //定义set
for_each(s.begin(),s.end(),[](int n){cout << n << " ";});
cout << endl;
list<int> li = {1,2,3,4,5}; //定义list
for_each(li.begin(),li.end(),[](int n){cout << n << " ";});
cout << endl;
int arr[] = {1,2,3,4,5}; //定义一个数组
for_each(arr,arr+5,[](int n){cout << n << " ";});
cout << endl;
//测试迭代器的模板函数
for_each(MiniSTL::begin(vec),MiniSTL::end(vec),[](int n){cout << n << " ";});
cout << endl;
for_each(MiniSTL::begin(s),MiniSTL::end(s),[](int n){cout << n << " ";});
cout << endl;
for_each(MiniSTL::begin(li),MiniSTL::end(li),[](int n){cout << n << " ";});
cout << endl;
for_each(MiniSTL::begin(arr),MiniSTL::end(arr),[](int n){cout << n << " ";});
cout << endl;
//测试获取首尾元素
cout << MiniSTL::front(vec) << "," << MiniSTL::back(vec) <<endl;
cout << MiniSTL::front(li) << "," << MiniSTL::back(li) <<endl;
cout << MiniSTL::front(s) << "," << MiniSTL::back(s) <<endl;
cout << MiniSTL::front(arr) << "," << MiniSTL::back(arr) <<endl;
}
模板函数中使用静态变量和类中变量的特殊情况:
#include <iostream>
using namespace std;
class Simple{
public:
static int Static;
class Test{};
typedef int Number;
};
int Simple::Static = 0; //类中的静态成员变量要在类外定义
template <typename T>
void Func(T& s){
T::Static; //模板认为类名(T::XXXX)只是在访问类的静态成员变量,而不是使用嵌套类定义的对象
typename T::Test n; //如果在模板中使用类里面定义的类型,必须在前面加上关键字typename
typename T::Test num; //这是typename的第二个作用,第一个作用是在声明模板的类型时使用
}
int main(){
Simple::Static;
Simple::Test n;//在非模板里面可以直接使用,不需要加上关键字typename
//类里面的静态成员变量和类内部类型的访问方式是一样的,类名::XXXX
Simple::Number num;
Simple s;
Func(s);
}