Java教程

STL迭代器

本文主要是介绍STL迭代器,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

 

目录

一、迭代器

基本概念

(1)内置迭代器的使用

(2)自己模拟迭代器的实现

(3)流型迭代器

二、lambda表达式

(1)基本概念

(2)捕获方式的区别

三、仿函数 包含头文件functional

基本概念

使用

四、函数适配器  包含头文件functional

(1)普通函数绑定

(2)类内成员函数绑定

(3)占位符表示原来的参数去第几位

五、函数包装器 包含头文件functional

(1)包装普通函数

(2)包装成员函数和静态函数

(3)包装仿函数

(4)更替参数顺序


一、迭代器

基本概念

迭代器:本质类中类,核心运算符重载
   迭代器的分类
     正向迭代器:iterator
         begin()
         end()
     反向迭代器reverse_iterator
         rbegin()
         rend()
     常正向迭代器 const_iterator
         cbegin()
         cend()
     常反向迭代器const_reverse_iterator
         crbegin()
         crend()

按功能分类
   正向迭代器
   双向迭代器
   随机访问迭代器
容器中迭代器分类  一般连续性内存都可用迭代器访问
    容器名      迭代器类型
    array         随机访问
    vector        随机访问
    deque         随机
    stack、queue、priority_queue    不支持
    list          双向
    set/multiset   双向
    map、multimap   双向

迭代器的辅助函数
  移动  advance(iterator iter,n)  
  间距  distance(iterator begin,iterator end) 
  交换  iter_swap(iterator first iterator second)

(1)内置迭代器的使用

#include<vector>
int main()
{
	vector<int> data = { 1,2,3,4,5,6,7,8,9 };
	vector<int>::iterator iter;
	//对象模仿指针的行为
	for (iter = data.begin();iter != data.end();iter++)
	{
		cout << *iter << " ";
	}
	cout << endl;
	//迭代器一般都是++操作无--操作
	auto rIter = data.rbegin();
	for (;rIter != data.rend();rIter++)
	{
		cout << *rIter << " ";
	}
	cout << endl;
	//区别在于常无法去修改数据
	vector<int>::const_iterator c_iter;
	for (c_iter = data.cbegin();c_iter != data.cend();c_iter++)
	{
		cout << *c_iter << " ";
	}
	cout << endl;
	return 0;
}

(2)自己模拟迭代器的实现

通过重载运算符的方式,将对象当指针使用

//节点
template<class _Ty>
struct Node
{
	_Ty data;
	Node<_Ty>* next;
	Node<_Ty>(_Ty data) :data(data), next(nullptr) {}
   //用作插入
	Node<_Ty>(_Ty data, Node<_Ty>* next) : data(data), next(next) {}
};

//链表 内部包含类中类iterator
template<class _Ty>
class My_List
{
public:
	My_List()
	{
		curSize = 0;
	}
//插入节点
	void push_front(int data)
	{
		if (curSize == 0)
		{
			frontNode = new Node<_Ty>(data);
			tailNode = frontNode;
		}
		else
		{
			frontNode = new Node<_Ty>(data, frontNode);
		}
		curSize++;
	}
	void print()
	{
		Node<_Ty>* pMove = frontNode;
		while (pMove != nullptr)
		{
			cout << pMove->data << " ";
			pMove = pMove->next;
		}
	}
//迭代器
	class iterator
	{
	public:
		iterator(Node<_Ty>* pMove=nullptr) :pMove(pMove) {}
		//由于用临时变量赋值,使用拷贝构造
		iterator(const iterator& object) :pMove(object.pMove) {}
		bool operator!=(const iterator& object) const
		{
			return this->pMove != object.pMove;
		}
		iterator operator++(int)
		{
			pMove = pMove->next;
			return iterator(pMove);
		}
		_Ty operator*()
		{
			return pMove->data;
		}
	protected:
		Node<_Ty>* pMove;
	};
	iterator begin()
	{
		return iterator(frontNode);
	}
	iterator end()
	{
		return iterator(nullptr);
	}
protected:
	Node<_Ty>* frontNode;
	Node<_Ty>* tailNode;
	int curSize;
};

void testList()
{
	My_List<int> list;
	list.push_front(1);
	list.push_front(2);
	list.push_front(3);
	list.print();
	My_List<int>::iterator iter = list.begin();
	for (;iter != list.end();iter++)
	{
		cout << *iter << " ";
	}
	cout << endl;
}

(3)流型迭代器

特殊迭代器(流型迭代器) 一般用在辅助打印
   输出流型(两种构造方式)
       ostream_iterator<_Ty> iter(ostream* out)
       ostream_iterator<_Ty> iter(ostream& out,char* str)
       输出流型迭代器赋值运算,就是把数据打印
   输入流型(两种构造方式)
        //构造无参对象,是错误流(输入错误类型返回错误)
        istream_iterator<_Ty> iter //*运算等效cin
       istream_iterator<_Ty> iter(istream& in)

#include<vector>
void test1()
{
	ostream_iterator<int> iter(cout);
	iter = 123;//打印到屏幕上
	//一般作为别的函数的参数 在打印数据后面
	ostream_iterator<int> iter2(cout,"欧拉欧拉");
	iter2 = 1432;

	vector<int> data = { 1,2,3,4 };
	//等效打印
	copy(data.begin(), data.end(), ostream_iterator<int>(cout, "\t"));
	//输入流型
	cout << "测试:" << endl;
	istream_iterator<int> end;
	istream_iterator<int> in(cin);
	vector<int> inputData;
	//反复输入 直到输入类型错误
	while (in != end)
	{
		inputData.push_back(*in);
		++in;//改变位置 使其能够重复输入
	}
	for (auto v : inputData)
	{
		cout << v << " ";
	}
	cout << endl;
 }

二、lambda表达式

(1)基本概念

就是一个返回函数指针的表达式
     注意,它的定义和返回函数指针是一起的
  组成部分  mutable:是否可以修改  exception:是否有异常
     [捕获方式](函数参数)mutable exception->函数返回类型{函数体}
     int Max(int a,int b)
     {
     return a>b?:a,b;
     }//完整写法
     int(*pMax)(int,int)=[](int a,int b)mutable noexcept->int{return a>b?:a,b;} 
     省略写法:中间描述词均可以省略
     auto ppMax=[](int a,int b){return a>b?:a,b;}
     
  

 //只需要短暂性局部使用 相当于函数定义声明
//定义函数指针
    int(*pMax)(int a, int b) = nullptr;
//函数实现
    auto pp = [](int a, int b) {return a > b ? a : b;};
//直接调用    
    cout << pp(1, 3);
    cout << [](int a, int b) {return a > b ? a : b;}(1, 3) << endl;

(2)捕获方式的区别

 捕获方式(函数使用外部变量的方式)
     [=]  值的方式捕获:如果在函数中修改不会影响到外部变量
     [&]  引用的方式捕获:同步到外部变量
     [this] 类的方式:捕获类中数据成员
     [] 不捕获任何变量
     组合方式
     [=,&]  x用引用的方式,其余用值的方式

class MM
{
public:
    void print()
    {//表示捕获的是类内的数据
        [this] {cout << name << " " << age << endl;}();
    }
protected:
    string name="mo";
    int age=12;
};
int main()
{    
    int data = 10101;//无参可以省略括号
    //1.用值的方式:在lambda不能充当左值,函数1调用不会因为值的改变而改变
    //即外界值在改变也不会影响函数
    auto pData = [=] {cout << data << endl;};
    pData();
    data = 8080;
    pData();

    //2.lambda可以改变值,并且会因为值的改变而改变
    auto pData2 = [&] {cout << data << endl;};

    //3.this方式
    MM mm;
    mm.print();

    //特殊 结合auto 类似函数模板
    auto pAuto = [](auto a, auto b)->auto{return a > b ? a : b;};
    cout << pAuto(1, 3);
    return 0;
}

三、仿函数 包含头文件functional

基本概念

 仿函数 类模仿函数调用行为 
  实质:无名对象调用重载的函数
  一般情况,仿函数做排序准则 或者一些算法的计算准则
  关键在于重载()

  标准库中的仿函数
      算术类
      关系类
      逻辑类
      选择、证明、投射等

使用

#include<map>
class Sum
{
public:
	int operator()(int a, int b)const
	{
		return a + b;
	}
protected:
};
int main()
{//自定义实现
	//重载()的调用
	Sum s;
	//显示调用
	cout <<"显示调用"<< s.operator()(1, 3) << endl;
	cout << "隐式调用" << s(1, 3) << endl;
	//类模仿调用的行为 也可用Sum{}(1,3) 主要起标识作用
	cout << "无名对象" << Sum()(1, 3) << endl;

//库内部分例子
	//算术
	cout << plus<int>{}(1, 3) << endl;
	//关系
	map<int, less<int>> map1;
	map<int, greater<int>> map2;
	//逻辑类 
	cout << logical_and<int>{}(1, 3);//&&

	return 0;
}

四、函数适配器  包含头文件functional

bind函数绑定 

(1)普通函数绑定

以下面例子为例 Max函数有两个参数 ,print函数传入的pMax只有一个参数

使用bind给Max绑定一个参数再传入print

int Max(int a, int b)
{
	return a > b ? a : b;
}
void print(int(*pMax)(int), int a)
{
	pMax(a);
}

int main()
{
	//只是单纯绑定一个参数 并未改变函数指针类型
	//std::placeholders::_1占位符
//绑定的函数指针,占位符,参数设置
	auto pMax = bind(Max, std::placeholders::_1, 100);//把第二个参数置为100
	cout << pMax(1);
	cout << pMax(1, 2);//完成绑定后 使用绑定值第二个参数无效

	return 0;
}

(2)类内成员函数绑定

class Test
{
public:
	void print(int a, int b, int c)
	{
		cout << a << " " << b << " " << c << endl;
	}
};
void testClass()
{
	Test test;
	auto testFunc = bind(&Test::print, test, std::placeholders::_1, std::placeholders::_2, 100);
	//此时调用不需要对象 直接调用
	testFunc(1, 3);
 }

(3)占位符表示原来的参数去第几位

void printData(int a, Test b, string str)
{
	cout << " 调用成功" << endl;
}
//通过占位符,调整参数位置 形成不同调用形态
//占位符表示原来的参数去第几位 1去第三位 Test()去第1位 "as"去第二位
void testExUser()
{
	auto testFunc = bind(printData,
		std::placeholders::_3, std::placeholders::_1, std::placeholders::_2);
	printData(1, Test(), "as");
	
	testFunc(Test(), "as", 1);
}

五、函数包装器 包含头文件functional

 一旦函数被包装,函数包装器可以替换函数指针直接调用
  函数包装器实例化传参:function<函数返回值类型(参数类型)>

(1)包装普通函数

int Max(int a, int b)
{
	cout << "包装普通函数" << endl;
	return a > b ? a : b;
}
int main()
{//int返回值类型 (int,int)参数类型
	function<int(int, int)> funcMax(Max);
	cout << funcMax(1, 3) << endl;
    return 0;
}

(2)包装成员函数和静态函数

class MM
{
public:
	void print(int a)
	{
		cout << "包装成员函数" << endl;
	}
	static void printStatic()
	{
		cout << "包装静态成员函数" << endl;
	}
};
int main()
{
    MM mm;
	function<void(int)> func(bind(&MM::print, &mm, std::placeholders::_1));
	func(1);

    function<void()> funcS(MM::printStatic);
	funcS();
    return 0;
}

(3)包装仿函数

class MM
{
public:
};
class Test
{
public:
	void operator()(string str)
	{
		cout << str << endl;
	}
};

int main()
{
    Test test;
	function<void(string)> func = test;
	func("包装仿函数");
return 0;
}

(4)更替参数顺序

class MM
{
public:
};
void printData(int a, MM mm, string str)
{
	cout << "bind与function结合" << endl;
}

void testFuncBind()
{
	function<void(string, int, MM)> pf = bind(printData,
		std::placeholders::_2, std::placeholders::_3, std::placeholders::_1);
	pf("as", 1, MM());
}

这篇关于STL迭代器的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!