IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++STL迭代器 -> 正文阅读

[C++知识库]C++STL迭代器

迭代器:

迭代器就是一个类种类,通过运算符重载类种类的对象去遍历容器

迭代器的分类

正向迭代器: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/multiset? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 双向

迭代器辅助函数

移动:advance(iterator iter,n);? ? ? ? 迭代器的移动

间距:distance(iterator begjin,iterator end);? ? ? ? 两个迭代器中间有多少个元素

交换:iter_swap(iterator first,iterator end);

拓展内容:特殊迭代器 流型迭代器(一半用在辅助打印)

输出流型:(两种构造方式)

ostream_iterator<_Ty> iter(ostream& out);

ostream_iterator<_Ty> iter(ostream& out,char* str);

输出流型迭代器做赋值运算,意味着就是打印数据到屏幕上

输入流型

istream_iterator<_Ty> iter;? ? ? ? //构造无参对象是一个错误流end_of_ostream? ? ? ?

(数据如果不满足输入格式就会返回一个错误流)

istream_iterator<_Ty> iter(istream& in);

*iter? ? ? ? 等效于cin>>操作

#include<iostream>
#include<vector>
#include<iterator>
using namespace std;

template<class _Ty>struct Node {
	_Ty data;
	Node<_Ty>* pNext;
	Node(_Ty data) :data(data), pNext(nullptr) {};
	Node(_Ty data, Node<_Ty>* pNext) :data(data), pNext(pNext) {};
};

template<class _Ty>class My_List {
public:
	My_List() :frontNode(nullptr), tailNode(nullptr) {
		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 push_back() {

	}
	Node<_Ty>* begin() {
		return frontNode;
	}
	Node<_Ty>* end() {
		return nullptr;	//返回临时变量,需要复制,准备一个拷贝构造
	}
	class iterator {
	public:
		iterator(Node<_Ty>* pmove = nullptr) :pmove(pmove) {}
		iterator(const iterator& object) :pmove(object.pmove) {}		//没有申请内存用浅拷贝即可

		bool operator!=(Node<_Ty>* pmove)const {
			return this->pmove != pmove;
		}
		iterator operator++(int) {//后置++需要int 但这里就不实现了
			pmove = pmove->pNext;
			return iterator(pmove);
		}
		_Ty operator*() {
			return pmove->data;
		}
	protected:
		Node<_Ty>* pmove;	//迭代器实质:通过这个数据成员进行访问链表

	};
	void printTest() {
		Node<_Ty>* pmove = frontNode;
		while (pmove != nullptr) {
			cout << pmove->data << "\t";
			pmove = pmove->pNext;
		}
		cout << endl;

	}
protected:
	Node<_Ty>* frontNode;
	Node<_Ty>* tailNode;
	int curSize;
};
void testMy_List() {
	My_List<int> list;
	list.push_front(1);
	list.push_front(2);
	list.push_front(3);
	list.printTest();
	My_List<int>::iterator myIter = list.begin();
	for (; myIter != list.end(); myIter++) {
		cout << *myIter << "\t";
	}
	cout << endl;
}
void testIterator() {
	vector<int> data = { 1,2,3,4,5,6,7,8 };
	vector<int>::iterator iter;
	for (iter = data.begin(); iter != data.end(); iter++) {	//正反向迭代器只有++
		//对象模仿指针行为
		cout << *iter << "\t";
	}
	cout << endl;
	vector<int>::reverse_iterator rIter;
	rIter = data.rbegin();
	//auto rIter = data.rbegin();

	for (; rIter != data.rend(); rIter++) {
		cout << *rIter << "\t";
	}
	cout << endl;

	vector<int>::const_iterator c_iter;
	for (c_iter = data.cbegin(); c_iter != data.cend(); c_iter++) {	//不能做修改
	//对象模仿指针行为
		cout << *c_iter << "\t";
	}
	cout << endl;
}
void testExFunction() {
	vector<int> data = { 1,2,3,4,5,6,7,8 };
	vector<int>::iterator iter = data.begin();
	advance(iter, 3);
	cout << *iter << endl;
	cout << "distance:" << distance(data.begin(), data.end()) << endl;
	iter_swap(data.begin(), data.end() - 1);
	for (auto v : data) {
		cout << v << " ";
	}
	cout << endl;
}
void testIoIterator() {
	ostream_iterator<int> iter(cout);
	iter = 1243214;	//就是把这串数字打印到屏幕上
	cout << endl;
	ostream_iterator<int> iter2(cout, "我爱你");		//一般成为别人函数参数
	iter2 = 1314520;		//可以批处理容器里面的数据
	cout << endl;
	vector<int> data = { 1,2,3,4,5,6,7,8 };
	//等效打印
	copy(data.begin(), data.end(), ostream_iterator<int>(cout, "\t"));		//构造一个无名的
	cout << endl;

	//输入流型迭代器
	cout << "输入;流型迭代器测试" << endl;
	istream_iterator<int> end;	//	end_of_stream;
	istream_iterator<int> in(cin);
	vector<int> inputData;
	while (in != end) {
		inputData.push_back(*in);
		++in;
	}
	for (auto v : inputData) {
		cout << v << "\t";

	}
	cout << endl;
}

int main() {
	//testIterator();
	testMy_List();
	testExFunction();
	testIoIterator();
	return 0;
}

Lambda表达式

Lambda:就是一个返回函数指针的表达式,它定义和返回值函数指针在一起的

Lambda表达式组成部分

//[捕获方式](函数参数)mutable exception->函数返回值类型{函数体}

int Max(int a,int b){

????????return a>b?a:b;

}

void print(){? ? ? ? //Max的Lambda表达式写法

? ? ? ? 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;??

????????}

}

//捕获方式-->函数使用外部变量的方式

值的方式捕获????????[=]:不会影响外部变量

引用的方式捕获? ? [&]:同步到外部变量

this指针的方式? ? ? [this]:捕获类中的数据成员

不捕获任何变量? ? []

组合的捕获方式? ? [=.&x]:x用引用方式捕获,其他变量用值的方式捕获? ? ? ??

#include<iostream>
using namespace std;
void print(int(*pMax)(int, int), int a, int b) {
	cout << pMax(a, b) << endl;
}
class MM {
public:
	MM(string name,int age):name(name="张三"), age(age=18) {}
	void print() {
		[this] {cout << name << "\t" << age << endl; }();	//定义和调用一步到位,注意虽然没有参数但是调用还是要加()
	}
protected:
	string name;
	int age;
};
int main() {
	int(*pMax)(int, int) = nullptr;
	pMax = [](int a, int b)mutable noexcept->int {
		return a > b ? a : b;
	};

	cout << pMax(1, 3) << endl;
	//省略版本
	auto pp = [](int a, int b) {return a > b ? a : b; };
	cout << pp(1, 3) << endl;
	//实际使用可以一步到位     一般短暂性的局部使用的函数用lambda函数实现,如回调函数
	cout << [](int a, int b)mutable noexcept->int {return a > b ? a : b; }(1, 3) << endl;

	print([](int a, int b)mutable noexcept->int {return a > b ? a : b; }, 1, 3);

	//捕获方式区别
	//用值的方式捕获:在Lambda中不能把值当作左值使用,函数的调用不会因为值的改变而改变
	int data = 101010;
	auto pFunc = [=] {cout << data << endl; };				//没有参数可以把参数省略
	auto pFunc2 = [&] {data,cout << data << endl; };
	pFunc();
	pFunc2();
	data = 9999;
	pFunc();
	pFunc2();

	MM mm("zhangsan",19);
	mm.print();

	//特殊的东西-->可以结合auto使用
	auto pAuto = [](auto a, auto b)->auto{return a > b ? a : b; };
	cout << pAuto(1, 3) << endl;	//因为实际在这里展开所以可以auto不赋值[](auto a, auto b)->auto{return a > b ? a : b; }(1,3)
	cout << pAuto("stringa", "stringb") << endl;	

	return 0;
}

仿函数

?什么是仿函数:

类模仿函数调用的行为,实质是无名对象调用重载的()函数

关键点在于重载()

一般情况仿函数是做排序准则或者一些算法的计算准则

标准库仿函数

算术类

关系类

逻辑类

选择,证同,投射

#include<iostream>
#include<string>
#include<functional>	//标准库仿函数头文件
using namespace std;
class Sum {
public:
	int operator()(int a, int b)const {
		return a + b;
	}
protected:

};
int main() {
	//重载()的调用
	//通过对象显示调用
	Sum sum;
	cout << "显示调用" << endl;
	sum.operator()(1, 2);
	//隐式调用
	cout << "隐式调用" << endl;
	sum(1, 2);
	//用(){}帮助编译器解析,实质不需要
	cout << "无名调用" << Sum()(1, 3) << endl;	//类模仿函数调用的行为-->仿函数

	//算数
	cout << plus<int>{}(1, 3) << endl;
	cout << minus<int>{}(1, 3) << endl;
	cout << multiplies<int>{}(1, 3) << endl;
	//关系
	cout << equal_to<int>{}(1, 3) << endl;
	cout << not_equal_to<int>{}(1, 3) << endl;
	cout << greater<int>{}(1, 3) << endl;
	cout << less<int>{}(1, 3) << endl;

	//逻辑
	cout << logical_and<int>{}(1, 3) << endl;
	//大于3小于10,花里胡哨写法
	int a = 34;
	if (logical_and<int>{}(a > 3, a < 10)) {
		cout << "这个数大于三小于十" << endl;
	}


	return 0;
}

函数适配器

什么是函数适配器?

用来绑定函数调用时侯的参数,让函数适应其他调用的用法。

#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<functional>
using namespace std;
//老版本bind1st bind2nd
//新版本bind函数
int Max(int a, int b) {
	return a > b ? a : b;
}
void print(int (*pMax)(int), int a) {
	cout << pMax(a) << endl;
}
class Test {
public:
	void print(int a, int b, int c) {
		cout << a << " " << b << " " << c << endl;
	}
protected:

};
void testClassFunc() {
	Test test;
	//注意两点1.类名取地址符,2.多一个参数,指明是哪个对象的
	auto testFunc = bind(&Test::print, &test, std::placeholders::_1, std::placeholders::_2, 99);
	//调用直接调用,不用对象
	testFunc(1, 3);
}
void printData(int one, Test two, string str) {
	cout << "调用成功" << endl;
}
//可以通过占位符,随意调整参数位置,形成不同调用形态
void testExUser() {
	auto testFunc = bind(printData, std::placeholders::_3, std::placeholders::_1, std::placeholders::_2);
	printData(1, Test(), "Iloveyou");
	//testFunc(1, Test(), "Iloveyou");	//报错
	//testFunc("ilove", 3, Test());		//报错,占位符代表的是原来的参数要去第几位
	testFunc(Test(), "Iloveyou", 3);
}
int main() {
	cout << Max(1, 3) << endl;
	//bind返回值是函数指针

	//using namespce std::placeholders
	auto pMax = bind(Max,std::placeholders::_1, 100);		//第一个参数是一个占位符,最多有20个占位符,把第二个参数置为100
	cout << pMax(23) << endl;
	cout << pMax(23,43) << endl;	//第二个参数不会是43,仍然是100
	//print(pMax, 23);
	vector<int> vecData = { 432,34,2,36,345,6,3,76,687,45433 };
	cout << count_if(vecData.begin(), vecData.end(), bind(greater<int>(), std::placeholders::_1, 60)) << endl;
	
	cout << count_if(vecData.begin(), vecData.end(), [](int a)mutable noexcept->int {return a > 60 ; }) << endl;

	testExUser();

	return 0;
}

函数包装器

什么是函数包装器?

就是把函数指针包装成一个对象,通过对象调用函数。

注意点:

一旦函数指针被函数包装器包装了,那这个包装器可以直接替换函数指针用法去调用函数。

函数包装器类的实例化传参:function<函数返回值类型(参数类型)>

#include<iostream>
#include<string>
#include<functional>
using namespace std;
int Max(int a, int b) {
	cout << "包装普通函数" << endl;
	return a > b ? a : b;
}
class MM {
public:
	void print(int a) {	//成员函数在解析的时候都会传入一个this指针,而static函数不会 void print(int a,MM* mm )
		cout << "包装成员函数" << endl;
	}
	static void printStatic() {
		cout << "包装静态的函数" << endl;
	}
protected:

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

};
//结合bind函数包装
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("string", 1, MM());
}
//包装成员函数
void testMMFunc() {
	MM mm;
	function<void(int)> func = bind(&MM::print, &mm, std::placeholders::_1);	//结合bind函数把this指针绑在一起
	func(23);
}
int main() {
	function<int(int, int)> funcMax(Max);
	cout << funcMax(1, 3) << endl;
	function<int(int, int)> funcMax2 = Max;
	function<void()> funS(MM::printStatic);
	funS();
	/*MM mm;
	function<void()> funMM(MM::print);*/

	Test test;
	function<void(string)> func = test;
	func("仿函数包装");
	

	TestFuncBind();
	return 0;
}

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-01-03 15:53:52  更:2022-01-03 15:54:10 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 10:33:20-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码