C++/C++11中头文件iterator的使用_#include <iterator>-程序员宅基地

技术标签: C/C++/C++11/14/17  

<iterator>是C++标准程序库中的一个头文件,定义了C++ STL标准中的一些迭代器模板类,这些类都是以std::iterator为基类派生出来的。迭代器提供对集合(容器)元素的操作能力。迭代器提供的基本操作就是访问和遍历。迭代器模拟了C++中的指针,可以有++运算,用*(解引用算符,deference)或->算符来访问容器中的元素。容器中元素如果改变了所用内存,也不影响绑定的迭代器指向正确的位置。因此,迭代器实际上更像是句柄(handler)。迭代器允许C++程序以统一的方式处理不同的数据结构。迭代器充当容器和通用算法之间的中介。而不是对特定数据类型进行操作,算法被定义为在一个迭代器类型指定的范围内运行。任何满足迭代器要求的数据结构都可以通过算法进行操作。

STL的迭代器实现了设计模式中的”迭代器模式”,即顺序访问一个聚合中的元素,又不暴露聚合的实现细节。

迭代器支持以不同方法遍历聚合类型。例如,对一颗树数据类型,可以有前序、中序、后序遍历的迭代器。同一个聚合类型的对象上,可以同时有多个迭代器,各自保持不同的遍历状态。在不同的聚合类型上实现的迭代器具有标准的对外接口,这给STL中的算法使用迭代器提供了可能。

一共支持五种迭代器:输入迭代器(*iter解引用后只能用作右值)、输出迭代器(*iter解引用后只能用作左值)、前向迭代器(具有输入迭代器、输出迭代器的所有功能,且可以反复遍历操作,支持对同一个元素的多次读写)、双向迭代器(是在前向迭代器的基础上,多了单步向后遍历的能力)、随机访问迭代器(在双向迭代器基础上,具有直接访问各数据元素的能力。随机迭代器增加了”迭代器算术运算”)。

std::input_iterator_tag:空类,标识一个迭代器的类别为输入迭代器。

std::output_iterator_tag:空类,标识一个迭代器的类别为输出迭代器。

std::forward_iterator_tag:空类,标识一个迭代器的类别为前向迭代器。

std::bidirectional_iterator_tag:空类,标识一个迭代器的类别为双向迭代器。

std::random_access_iterator_tag:空类,标识一个迭代器的类别为随机迭代器。

下面是从其它文章中copy的<iterator>测试代码,详细内容介绍可以参考对应的reference:

 

#include "iterator.hpp"
#include <iterator>
#include <iostream>
#include <typeinfo>
#include <list>
#include <vector>
#include <algorithm>
#include <deque>
#include <string>

// reference: http://www.cplusplus.com/reference/iterator/

namespace iterator_ {
///
class MyIterator : public std::iterator<std::input_iterator_tag, int>
{
public:
	MyIterator(int* x) :p(x) {}
	MyIterator(const MyIterator& mit) : p(mit.p) {}
	MyIterator& operator++() { ++p; return *this; }
	MyIterator operator++(int) { MyIterator tmp(*this); operator++(); return tmp; }
	bool operator==(const MyIterator& rhs) const { return p == rhs.p; }
	bool operator!=(const MyIterator& rhs) const { return p != rhs.p; }
	int& operator*() { return *p; }
private:
	int* p;
};

int test_iterator_1()
{
	// std::iterator: 迭代器基类
	int numbers[] = { 10, 20, 30, 40, 50 };
	MyIterator from(numbers);
	MyIterator until(numbers + 5);
	for (MyIterator it = from; it != until; it++)
		std::cout << *it << ' ';
	std::cout << '\n';

	return 0;
}

/
int test_iterator_2()
{
	// std::iterator_traits: 定义迭代器属性
	typedef std::iterator_traits<int*> traits;
	if (typeid(traits::iterator_category) == typeid(std::random_access_iterator_tag))
		std::cout << "int* is a random-access iterator" << std::endl;;

	return 0;
}

///
int test_iterator_3()
{
	// std::advance: 将迭代器推进到n个元素位置,可以是负值
	std::list<int> mylist;
	for (int i = 0; i<10; i++) mylist.push_back(i * 10);

	std::list<int>::iterator it = mylist.begin();

	std::advance(it, 5);

	std::cout << "The sixth element in mylist is: " << *it << '\n'; // 50

	return 0;
}


int test_iterator_4()
{
	// std::back_inserter: 构造一个在x的末尾插入新元素的后插入迭代器
	std::vector<int> foo, bar;
	for (int i = 1; i <= 5; i++) {
		foo.push_back(i); bar.push_back(i * 10);
	}

	std::copy(bar.begin(), bar.end(), std::back_inserter(foo));

	std::cout << "foo contains:";
	for (std::vector<int>::iterator it = foo.begin(); it != foo.end(); ++it)
		std::cout << ' ' << *it; // 1 2 3 4 5 10 20 30 40 50
	std::cout << '\n';

	return 0;
}

//
int test_iterator_5()
{
	// std::begin: 返回指向序列中第一个元素的迭代器
	// std::end: 返回指向序列中过去的最后一个元素的迭代器
	int foo[] = { 10, 20, 30, 40, 50 };
	std::vector<int> bar;

	// iterate foo: inserting into bar
	for (auto it = std::begin(foo); it != std::end(foo); ++it)
		bar.push_back(*it);

	// iterate bar: print contents:
	std::cout << "bar contains:";
	for (auto it = std::begin(bar); it != std::end(bar); ++it)
		std::cout << ' ' << *it; // 10 20 30 40 50
	std::cout << '\n';

	return 0;
}

//
int test_iterator_6()
{
	// std::distance: 计算first和last之间的元素数量
	std::list<int> mylist;
	for (int i = 0; i<10; i++) mylist.push_back(i * 10);

	std::list<int>::iterator first = mylist.begin();
	std::list<int>::iterator last = mylist.end();

	std::cout << "The distance is: " << std::distance(first, last) << '\n'; // 10

	return 0;
}


int test_iterator_7()
{
	// std::front_inserter: 构造一个前插入迭代器,在x的开头插入新元素
	std::deque<int> foo, bar;
	for (int i = 1; i <= 5; i++) {
		foo.push_back(i); bar.push_back(i * 10);
	}

	std::copy(bar.begin(), bar.end(), std::front_inserter(foo));

	std::cout << "foo contains:";
	for (std::deque<int>::iterator it = foo.begin(); it != foo.end(); ++it)
		std::cout << ' ' << *it; // 50 40 30 20 10 1 2 3 4 5
	std::cout << '\n';

	return 0;
}

//
int test_iterator_8()
{
	// std::inserter: 构造一个插入迭代器,从指向的位置开始,在连续的位置中插入新元素x
	std::list<int> foo, bar;
	for (int i = 1; i <= 5; i++) {
		foo.push_back(i); bar.push_back(i * 10);
	}

	std::list<int>::iterator it = foo.begin();
	std::advance(it, 3);

	std::copy(bar.begin(), bar.end(), std::inserter(foo, it));

	std::cout << "foo contains:";
	for (std::list<int>::iterator it = foo.begin(); it != foo.end(); ++it)
		std::cout << ' ' << *it; // 1 2 3 10 20 30 40 50 4 5
	std::cout << '\n';

	return 0;
}


int test_iterator_9()
{
	// std::make_move_iterator: 从it构造一个move_iterator对象
	std::vector<std::string> foo(3);
	std::vector<std::string> bar{ "one", "two", "three" };

	std::copy(std::make_move_iterator(bar.begin()), std::make_move_iterator(bar.end()), foo.begin());

	// bar now contains unspecified values; clear it:
	bar.clear();

	std::cout << "foo:";
	for (std::string& x : foo) std::cout << ' ' << x; // one two three
	std::cout << '\n';

	return 0;
}

//
int test_iterator_10()
{
	// std::next: 获取下一个元素的迭代器
	std::list<int> mylist;
	for (int i = 0; i<10; i++) mylist.push_back(i * 10);

	std::cout << "mylist:";
	std::for_each(mylist.begin(), std::next(mylist.begin(), 5), [](int x) {std::cout << ' ' << x; }); // 0 10 20 30 40 50

	std::cout << '\n';

	return 0;
}

//
int test_iterator_11()
{
	// std::prev: 获取前一个元素的迭代器
	std::list<int> mylist;
	for (int i = 0; i<10; i++) mylist.push_back(i * 10);

	std::cout << "The last element is " << *std::prev(mylist.end()) << '\n'; // 90

	return 0;
}


int test_iterator_12()
{
	// std::back_insert_iterator: 在容器末尾插入元素的迭代器
	std::vector<int> foo, bar;
	for (int i = 1; i <= 5; i++) {
		foo.push_back(i); bar.push_back(i * 10);
	}

	std::back_insert_iterator< std::vector<int> > back_it(foo);

	std::copy(bar.begin(), bar.end(), back_it);

	std::cout << "foo:";
	for (std::vector<int>::iterator it = foo.begin(); it != foo.end(); ++it)
		std::cout << ' ' << *it; // 1 2 3 4 5 10 20 30 40 50 
	std::cout << '\n';

	return 0;
}

///
int test_iterator_13()
{
	// std::front_insert_iterator: 在容器开头插入元素的迭代器
	std::deque<int> foo, bar;
	for (int i = 1; i <= 5; i++) {
		foo.push_back(i); bar.push_back(i * 10);
	}

	std::front_insert_iterator< std::deque<int> > front_it(foo);

	std::copy(bar.begin(), bar.end(), front_it);

	std::cout << "foo:";
	for (std::deque<int>::iterator it = foo.begin(); it != foo.end(); ++it)
		std::cout << ' ' << *it; // 50 40 30 20 10 1 2 3 4 5
	std::cout << '\n';

	return 0;
}

//
int test_iterator_14()
{
	// std::insert_iterator: 插入迭代器
	std::list<int> foo, bar;
	for (int i = 1; i <= 5; i++) {
		foo.push_back(i); bar.push_back(i * 10);
	}

	std::list<int>::iterator it = foo.begin();
	std::advance(it, 3);

	std::insert_iterator< std::list<int> > insert_it(foo, it);

	std::copy(bar.begin(), bar.end(), insert_it);

	std::cout << "foo:";
	for (std::list<int>::iterator it = foo.begin(); it != foo.end(); ++it)
		std::cout << ' ' << *it; // 1 2 3 10 20 30 40 50 4 5
	std::cout << '\n';

	return 0;
}

///
int test_iterator_15()
{
	// std::istreambuf_iterator: 输入流缓存迭代器
	std::istreambuf_iterator<char> eos;                    // end-of-range iterator
	std::istreambuf_iterator<char> iit(std::cin.rdbuf()); // stdin iterator
	std::string mystring;

	std::cout << "Please, enter your name: ";

	while (iit != eos && *iit != '\n') mystring += *iit++;

	std::cout << "Your name is " << mystring << ".\n";

	return 0;
}

///
int test_iterator_16()
{
	// std::istream_iterator: 从输入流读取连续元素的输入迭代器
	double value1, value2;
	std::cout << "Please, insert two values: ";

	std::istream_iterator<double> eos;              // end-of-stream iterator
	std::istream_iterator<double> iit(std::cin);   // stdin iterator

	if (iit != eos) value1 = *iit;

	++iit;
	if (iit != eos) value2 = *iit;

	std::cout << value1 << "*" << value2 << "=" << (value1*value2) << '\n';

	return 0;
}

///
int test_iterator_17()
{
	// std::move_iterator: 用于解引用(Dereference)到一个右值引用(Rvalue reference)的迭代器
	std::vector<std::string> foo(3);
	std::vector<std::string> bar{ "one", "two", "three" };

	typedef std::vector<std::string>::iterator Iter;

	std::copy(std::move_iterator<Iter>(bar.begin()), std::move_iterator<Iter>(bar.end()), foo.begin());

	// bar now contains unspecified values; clear it:
	bar.clear();

	std::cout << "foo:";
	for (std::string& x : foo) std::cout << ' ' << x; // one two three
	std::cout << '\n';

	return 0;
}

///
int test_iterator_18()
{
	// std::ostreambuf_iterator: 输出流缓存迭代器
	std::string mystring("Some text here...\n");
	std::ostreambuf_iterator<char> out_it(std::cout); // stdout iterator

	std::copy(mystring.begin(), mystring.end(), out_it); // Some text here...

	return 0;
}

/
int test_iterator_19()
{
	// std::ostream_iterator: 顺序写入输出流的输出迭代器
	std::vector<int> myvector;
	for (int i = 1; i<10; ++i) myvector.push_back(i * 10);

	std::ostream_iterator<int> out_it(std::cout, ", ");
	std::copy(myvector.begin(), myvector.end(), out_it); // 10, 20, 30, 40, 50, 60, 70, 80, 90, 

	return 0;
}

///
int test_iterator_20()
{
	// std::reverse_iterator: 反向迭代器
	std::vector<int> myvector;
	for (int i = 0; i<10; i++) myvector.push_back(i);

	typedef std::vector<int>::iterator iter_type;
							      // ? 0 1 2 3 4 5 6 7 8 9 ?
	iter_type from(myvector.begin());                     //   ^
							      //         ------>
	iter_type until(myvector.end());                      //                       ^
							      //
	std::reverse_iterator<iter_type> rev_until(from);     // ^
							      //         <------
	std::reverse_iterator<iter_type> rev_from(until);     //                     ^

	std::cout << "myvector:";
	while (rev_from != rev_until)
		std::cout << ' ' << *rev_from++; // 9 8 7 6 5 4 3 2 1 0
	std::cout << '\n';

	return 0;
}

} // namespace iterator_


GitHubhttps://github.com/fengbingchun/Messy_Test

 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/fengbingchun/article/details/77985191

智能推荐

Rocket MQ(四)Topic,Topic分片和Queue-程序员宅基地

文章浏览阅读1.1w次,点赞11次,收藏59次。Queue是RocketMQ中的另一个重要概念。在对该概念进行分析介绍前,我们先来看一张图:从本质上来说,RocketMQ中的Queue是数据分片的产物。为了更好地理解Queue的定义,我们还需要引入一个新的概念:Topic分片。在分布式数据库和分布式缓存领域,分片概念已经有了清晰的定义。同理,对于RocketMQ,一个Topic可以分布在各个Broker上,我们可以把一个Topic分布在一个Broker上的子集定义为一个Topic分片。对应上图,TopicA有3个Topic分片,分布在Broker

彻底解决Compiling for iOS xxx, but module ‘xxx‘ has a minimum deployment target of iOS xxx 错误_compiling for ios 9.0, but module 'reactiveswift' -程序员宅基地

文章浏览阅读1.1w次。target ios版本和第三方库ios版本问题问题描述解决方法查看iphone iPad target的最低ios版本修改pod里第三方库问题描述这几天编辑xcode偶尔会发现这个错误,但是有时候重新编译一下错误就消失了,今天彻底解决一下这个错误错误提示:Compiling for iOS 10.0, but module ‘SwiftyJSON’ has a minimum deployment target of iOS 12.0: /Users/tdw/Library/Developer/Xc_compiling for ios 9.0, but module 'reactiveswift' has a minimum deployment t

Android NDK thread 回收crash, signal 4 (SIGILL), code 1 (ILL_ILLOPC) , fault addr 地址-程序员宅基地

文章浏览阅读2.8k次。Android NDK thread 回收crash, signal 4 (SIGILL), code 1 (ILL_ILLOPC) , fault addr 地址在NDK c++ 使用pthread_create 创建线程,不管是可分离线程还是非可分离的线程,在回收的时候都有这个问题,ndk-stack 定位到的问题行发现一切正常,卡了好几天,网上查了好久,看到了一篇帖子https://w...

NOI题库答案 (1.7 字符串基础)(1-20)-程序员宅基地

文章浏览阅读1.9w次,点赞20次,收藏64次。 01:统计数字字符个数描述输入一行字符,统计出其中数字字符的个数。输入一行字符串,总长度不超过255。输出输出为1行,输出字符串里面数字字符的个数。样例输入Peking University is set up at 1898.样例输出4#include&lt;bits/stdc++.h&gt;using namespace std;in...

传授人生经验(预处理)_轩神与奇牛是师徒,也是k友,经常打2k,可奇牛老是不故意放水让轩神输,于是轩神决定-程序员宅基地

文章浏览阅读769次。Description轩神与奇牛是师徒,也是K友,经常打2K,可奇牛老是不故意放水让轩神输,于是轩神决定给奇 牛传授点人生经验以作补偿。 轩神拿出其珍藏多年的人生经验打造了n个经验球并连成一串,每一 个球里都含着一定量的人生经验。好玩的是,你打破一个球,你没法获得里面的人生经验,而只 能获得打破的那个球两边球的经验绝对值差。 假设轩神造了5个球,按顺序为 1 2 3 4 5 那么打破_轩神与奇牛是师徒,也是k友,经常打2k,可奇牛老是不故意放水让轩神输,于是轩神决定

以Vivado工具为例了解FPGA综合-程序员宅基地

文章浏览阅读4.3k次,点赞11次,收藏88次。在设计过程中,各个阶段的生成的文件都是.dcp,Vivado使用的是通用的模型贯穿在设计。_fpga综合

随便推点

SpringCloud之高可用的分布式配置中心(Spring Cloud Config)(七)-程序员宅基地

文章浏览阅读39次。当服务实例很多时,都从配置中心读取文件,这时可以考虑将配置中心做成一个微服务,将其集群化,从而达到高可用,架构图如下:准备工作继续使用上一篇文章的工程,创建一个eureka-server工程,用作服务注册中心。在其pom.xml文件引入Eureka的起步依赖spring-cloud-starter-netflix- eureka-server,代码如下:<?xml version=...

c语言中.和->区别,c语言中"->"和"."的区别-程序员宅基地

文章浏览阅读3.5k次,点赞7次,收藏21次。对于c语言中"->"和"."的区别总结如下:1、A.B则A为对象或者结构体;2、A->B则A为指针,->是成员提取,A->B是提取A中的成员B,A只能是指向类、结构、联合的指针;3、(*a).b 等价于 a->b。"."一般情况下读作"的”; “->”一般读作"指向的结构体的"。也就是说在结构中,运算符->是运算符*和运算符.的结合4、“->”是指向..._->和.

ubuntu20.04安装ROS2 详细教程-程序员宅基地

文章浏览阅读2.1w次,点赞27次,收藏218次。ubuntu20.04安装ROS2_ubuntu20.04安装ros2

人工智能之华为云5G基站有AI,智能处理流量“潮汐”-程序员宅基地

文章浏览阅读1.9k次,点赞3次,收藏16次。一、5G 基站能否智能“省电”?① 能耗和能效随着中国 5G 基站部署规模的扩大,5G 基站能耗惊人的说法甚嚣尘上,众口铄金,5G 基站似乎坐实“电老虎”的尴尬地位。如下是一张某运营商的内部流出照片,从中可以看出,5G AAU 和 4G RRU 的满载功耗相差极为悬殊,不得不承认 5G 的能耗确实远高于 4G:在移动的节能技术白皮书中,也明确地写着:“2019 年初 5G 基站功耗约为 4G 基站的 3~4 倍,高功耗是运营商大规模部署 5G 的棘手问题”:联通也在其白皮书中写道:“5

flyme8.1.5.0A精简内置软件包_flyme8精简-程序员宅基地

文章浏览阅读6k次。flyme8.1.5.0A系统精简内置软件包提示:精简系统有风险 在精简之前先备份资料 sdcard目录放置官网刷机包以备重新刷机在pc端用adb命令精简手机系统手机端打开usb调试模式 设置 ———关于手机————版本号 点击6~8次进入开发者模式设置————辅助功能————开发者选项————开启开发者选项 打开usb调试platform-tools下载地址https://developer.android.com/studio/releases/platfor_flyme8精简

解决盲注编码问题-程序员宅基地

文章浏览阅读366次。Traceback (most recent call last): File "E:/Pycharm Project/CTF/xman-ctf��¼.py", line 56, in <module> if accesss(urllib.unquote(sub_tables(i, w))): File "E:/Pycharm Project/CTF/xman-ctf��..._codefever盲注