重庆分公司,新征程启航

为企业提供网站建设、域名注册、服务器等服务

泛型编程风格-创新互联

目录

创新互联公司一直秉承“诚信做人,踏实做事”的原则,不欺瞒客户,是我们最起码的底线! 以服务为基础,以质量求生存,以技术求发展,成交一个客户多一个朋友!为您提供成都网站设计、成都网站制作、成都网页设计、成都微信小程序、成都网站开发、成都网站制作、成都软件开发、成都App定制开发是成都本地专业的网站建设和网站设计公司,等你一起来见证!

一.指针的算术运算

二.了解Iterator(泛型指针)

三.所有容器的共通操作

四.使用顺序性容器

五.使用泛型算法

六.设计泛型算法

七.map和set

八.使用iostream iterator


一.指针的算术运算

利用指针的算术运算完成find()函数的c++代码:

#include#includeusing namespace std;

templateT1* find(const T1* first, const T1* last, const T2 value) //第一和第二个参数用于表示所搜索的容器范围(两个指针表示范围),第三个参数为在容器中搜索的值。
{
	if (!first || !last)
	{
		return 0;
	}
	for (; first != end; first++) //end指针所指的位置应该是容器最后一个元素的下一个地址,这样才可以保证容器中的所有元素都经过了扫描
	{
		if (*first == value)
		{
			return first;
		}
	}
	return 0;
}


int main()
{
	int arr1[5] = { 5,3,10,9,6 };
	int* p1 = find(arr1, arr1 + 5, 9); //第一个参数是容器的首地址,第二个参数是容器的最后一个元素的下一个地址,即为尾地址
	if (p1 != (arr1 + 5))
	{
		cout<< "找到了,地址为:"<

知识点:

1.*(array+i) 与 array[i]的效果相同,下标操作就是将array的起始地址加上索引值,产出某个元素的地址,然后该地址再被提纲以返回元素值。

2.对于数组最后一个元素的下一个地址,只能对此地址进行比较,而不能用来读取和写入。

eg:

int ia[5] = {1,2,3,4,5};
int a1 = *(ia+6);//错误,对最后一个元素的下一个地址不能用来读取和写入
find(ia,ia+5,ia[3]);//正确,对最后一个元素的下一个元素可以用来比较

3.array数组不能为空,但是vector数组可以为空,同时vector类含有函数“ .empty "来判断一个vector数组是否为空。

4.对于list容器,不适用于指针的算术运算,因为指针的算术运算必须首先假设所有元素都存储在连续的空间里,但是list容器不存储在连续的空间里,其每个节点都有三个值:front指向上一个节点,next指向下一个节点,value表示节点的值。

参考文章:C++ list(STL list)容器完全攻略(超级详细) (biancheng.net)

5.list容器适用于存储常需要修改(插入删除操作)而不常读取的数据,而vector和array容器适用于存储常读取而不常修改(插入删除操作)的数据。

二.了解Iterator(泛型指针)

通过iterator指针实现find()函数的C++代码:

#include#include#include#includeusing namespace std;

const int asize = 5;

templateIteratorType find1(IteratorType first, IteratorType last,const elemType value) //同理,第一个参数是容器的第一个元素的地址,而第二个参数是容器最后一个元素的下一个地址
{
	for (; first != last; first++)
	{
		if (*first == value)
		{
			return first;
		}
	}
	return last; //此地址只可以用来比较,而不能用来读取和写入
}

int main()
{
	int ia[asize] = { 1,5,10,20,95 };
	vectorivec(ia, ia + asize);
	listilist(ia, ia + asize);

	int* pia = find1(ia, ia + asize, 20);
	if (pia != 0)
	{
		cout<< "找到了"<< endl;
	}

	vector::iterator iter1;
	iter1 = find1(ivec.begin(), ivec.end(), 100);
	if (iter1 != ivec.end())
	{
		cout<< "找到了"<< endl;
	}

	list::iterator iter2;
	iter2 = find1(ilist.begin(), ilist.end(), 95);
	if (iter2 != ilist.end())
	{
		cout<< "找到了"<< endl;
	}

	system("pause");
	return 0;
}

支持两种形式:一对指针或是一对指向某种容器的iterator

知识点:

1.对于不同类型的iterator指针,其运算符进行的操作是根据iterator class内相关的inline函数提供的。

eg:

//first是一个iterator泛型指针
first++;
//如果first是vector的泛型指针,则first++则是将目前的地址加上一个元素的大小。
//如果first是list的泛型指针,则first++则是会沿着list的指针前进到下一个元素。

2.每个标准容器都提供有一个begin()的操作函数,可返回一个iterator指向第一个元素, 也提供一个end()的操作函数指向最后一个元素的下一位置。

3.定义iterator:需要提供两个参数

(1).迭代对象(即为某个容器)的类型,用来决定如果访问下一元素。

(2).iterator所指的元素类型,可以决定iterator提领操作的返回值。

//iteratoriter1;
//iteratoriter2;
//实际语法:
vector::iterator iter1;
list::iterator iter2;

4.const_iterator:只可读而不可进行其他操作

vector::const_iterator iter;

5.通过iterator指针访问容器内的操作:间接访问( ->)

vector::iterator iter;
int size = iter->size();

三.所有容器的共通操作

①." == " 和 "!="运算符,返回true或false。

②."="运算符,将某个容器复制给另一个容器。

③.empty()会在容器无任何元素时返回true,否则返回false。

④.size()返回容器内目前持有的元素个数。

⑤.clear()删除所有元素。

⑥.begin()返回一个iterator指向容器的第一个元素,end()返回一个iterator指向容器的最后一个元素的下一位置。

⑦.insert()将单一或某个范围内的元素插入容器内,erase()将容器内的单一元素或者某个范围内的元素删除。

四.使用顺序性容器

1.顺序容器用来维护一组排列有序、类型相同的元素。

2.顺序性容器种类:

①.vector:以一块连续内存来存放元素,其中的每个元素都被存储在距离起始点的固定偏移位置上,随机访问效率较高,而对于任意位置的插入或删除操作缺乏效率。

②.list:以双向链接而非连续内存来存储内容,对于任意位置的插入或删除操作都颇具效率,但是随机访问操作则效率不高。(存放元素的内存不连续,因此不支持iterator的偏移运算)

③.deque:以连续内存来存放元素,与vector类似,但同时对于最前端和最后端元素的插入、删除操作效率更高。

3.定义顺序性容器方法:

①.产生空容器:

listslist;
vectorivec;

②.产生特定大小的容器,每个元素都以其默认值作为初值。(eg.int和double类型的默认值为0)

vectorivec(10);
listilist(20);

③.产生特定大小的容器,并为每个元素指定初值。

vectorivec(1024,10);
listilist(10,5.20);

④.通过一对iterator产生容器。这对iterator用来标示一整组作为初值的元素的范围。

int ia[5] = {1,2,3,4,5};
vectorivec(ia,ia+5);
listilist(ia,ia+5);

⑤.根据某个容器产出新容器。复制原容器内的元素,作为新容器的初值。

listilist1;
listilist2(ilist1);

4.三种顺序性容器都有push_back()和pop_back()函数,但只有list和deque容器拥有push_front()和pop_front()函数。

5.insert函数的变形函数(除push_front()和push_back()外)

①.

iterator insert(ierator position,elemType value);

将value值插入position之前,同时会返回一个iterator指向被插入的元素。

②.

void insert(iterator position,int count,elemType value);

在position前插入count个元素,这些元素的值都和value的相同。

③.

void insert(iterator position,iterator2 first,iterator2 last);

可在position之前插入[first,last)所标示的各个元素。

④.

iterator insert(iterator position);

在position之前插入元素,元素的初值为其所属属性的默认值。

6.erase()函数的变形函数(除pop_front()和pop_back()外)

①.

iterator erase(iterator position);

删除position所指的元素。

②.

iterator erase(iterator first,iterator last);

删除[first,last)范围内的元素。

五.使用泛型算法

1.使用泛型算法需要包含对应的头文件"algorithm";

#include

2.常用泛型搜索算法:

①.find()用于搜索无序集合中是否存在某值。搜索范围由iterator[first,last)标出。如果找到目标, find()会返回一个iterator指向该值,否则返回一个iterator指向last。

iterator find(iterator first, iterator last, elemType value);

②.binary_search()用于有序集合的搜索。如果搜索到目标则返回true,否则返回false。binary_search比find()更有效率。

bool binary_search(containerTypename, elemType value);

③.count()返回数值相符的元素数目。

④.search()比对某个容器内是否存在某个子序列。例如给定序列{1,3,5,7,2,9},如果搜索子序列{5,7,2},则search()会返回一个iterator指向子序列起始处。如果子序列不存在,就返回一个iterator指向容器末尾。

3.取得数列大元素值:max_element()。将一对iterator传给max_element(),它会返回该范围内的大值。

elemType max_element(iterator first,iterator last);

4.复制容器:copy()。将一对iterator传给copy()标示出复制范围,第三个iterator指向复制行为的目的地。

void copy(iterator1 first,iterator1 last,iterator2 begin);
六.设计泛型算法

泛型算法filiter()的C++代码:

#include//#include//使用function objectL less#include#include ///使用泛型算法find_if()
using namespace std;


templateOutputIterator filter(InputIterator first, InputIterator last, OutputIterator at, const ElemType& value, comp pred) //参数分别为传入容器的范围,传入容器的首地址,用于比较的值,比较类型函数
{
	while ((first = find_if(first, last, bind2nd(pred, value))) != last)
	{
		cout<< "found value: "<< *first<< endl;
		//将过滤后的数据放到新的容器,同时更新相应位置:
		*at++ = *first++;
	}
}

int main()
{
	const int elem_size = 8;
	int is[ elem_size ] = { 12,8,43,0,66,21,3,7 };
	vectorivec(elem_size);
	cout<< "过滤数组中小于8的值:"<< endl;
	filter(is, is + elem_size, ivec.begin(), elem_size,less());


	system("pause");
	return 0;
}

知识点:

1.若要使用事先定义的function object,需包含头文件:#inclucde

(visual studio 2022中已无法打开源文件)

其中包括:

①.六个算术运算:plus,minus,multiplies,divides,negate,modules

②.六个关系运算:less,less_equal,greater,greater_equal,equal_to,not_equal_to

③.三个逻辑运算,分别对应&&、||、!:logical_and,logical_or,logical_not

2.适配器adapter:

①.binder adapter:使binary(二元)fuction object转化为unary(一元)fuction object。

(1).bind1st:将指定值绑定至第一操作数。

bind1st(less,val);
//相当于: val<

(2).bind2nd:将指定值绑定至第二操作数。

bind2nd(less,val);
//相当于

②.negator adapter:对function object的真伪值取反。

(1).not1可对unary function object的真伪值取反。

not1(bind2nd(less,value));
//小于取反得到大于或等于

(2).not2可对binary function object的真伪值取反。

③.insertion adapter: 使用需要包含头文件

不能在array上使用,因为array不支持元素插入操作

可以对为设置大小的容器进行插入操作,但不能进行赋值操作

(1).back_inserter()会以容器的push_back()函数取代assignment运算符,参数为复制的目标容器。

(2).inserter()会以容器的insert()函数取代assignment运算符,接受两个参数,一个是复制的目标容器,另外一个是iterator指向容器内的插入操作起点。

(3).front_inserter()会以容器的push_front()函数取代assignment运算符,参数为复制的目标容器。同时这个inserter只适用于list和deque。

filter(ivec.begin(),ivec.end(),back_inserter(ivec2),elem_size,greater);
//第三个参数从最初的ivec2变为了back_inserter(ivec2)
//此操作使push_back()函数替代assignment运算符将元素复制到ivec2容器中
七.map和set

1.使用map和set分别需要包含头文件

2.使用map:

(1).map被定义为一对数值:

mapmapname;

其中的key通常是个字符串,扮演索引的角色,value则是key对应的值。

(2).map有两个member,分别为first指向key,second指向value:

mapm1;
 map::const_iterator it = m1.begin();
 it->first; //key
 it->second; //value

(3).查询某个map内是否存在某个key:

①.把key当作索引使用:

int count = 0 ;
if(!(count = words["vermeer"]));

原理:若map中不存在某个key,则会将此key放到map中并获得默认值0。

②.通过map的find()函数:

map::iterator::it = words.find("vermeer");

原理:如果key在map中,则会返回一个iterator指向key/map形成的一个pair,如果key不在map中则会返回end()。

③.通过map的count()函数:

if(words.count("vermeer"));

原理:count()函数返回key项在map内的个数。

3.使用set

(1).set由一群key组合而成:

setiset;

(2).set的insert()函数:

①加入单一元素:使用单一参数的insert():

iset.insert(ival);

②加入某个范围的元素,使用双参数的insert():

iset.insert(vec.begin(),vec.end());

(3).set元素皆依据其所属类型默认的less-than(递增)运算符进行排列。

4.任何一个key在map和set中最多只会有一份,如果需要储存多份相同的key值,则必须使用multimap和multiset。

八.使用iostream iterator
#include#include//istream_iterator, ostream_iterator
#include //copy(),sort()
#include#includeusing namespace std;

int main()
{
	istream_iteratoris(cin); //first
	istream_iteratoreof; //end

	vectortext;
	//输入:
	cout<< "输入:"<< endl;
	copy(is, eof, back_inserter(text));

	sort(text.begin(), text.end());

	ostream_iteratoros(cout, " ");
	//输出:
	cout<< "输出:"<< endl;
	copy(text.begin(), text.end(), os);

	system("pause");
	return 0;
}

知识点:

1.包含头文件使用iostream iterator类 -- istream_iterator和ostream_iterator,分别支持单一类型的元素读取和写入。

2.需要提供一对iterator:first和last用来表示元素范围:

指定istream对象即为first

不指定istream对象即为end-of-file

istream_iteratoris(cin); --- first; //指定istream对象即为first
istream_iteratoreof; --- last; //不指定istream对象即为end-of-file

3.创建ostream_iterator来标示字符串元素的输出位置:

ostream_iteratoros(cout," "):

第二个参数可以是C-style字符串,也可以是字符串常量,用来表示各个元素被输出时之间的分隔符。

4.使用copy()来进行输入和输出:

输入:

copy(is,eof,back_inserter(text));

输出:

copy(text.begin(),text.end(),os)

5.使用iostream_iterator完成从文件中读取,写到文件中去:

将istream_iterator绑定至ifstream object,并将ostream_iterator绑定至ofstream object。

ifstream in_file("input_file.txt");
ofstream out_file("output_file.txt");

istream_iteratoris(in_file); //first;
istream_iteratoreof; // last;

ostream_iteratoros(out_file," ");

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


新闻名称:泛型编程风格-创新互联
URL链接:http://cqcxhl.cn/article/icsec.html