泛型编程风格-创新互联
目录
创新互联公司一直秉承“诚信做人,踏实做事”的原则,不欺瞒客户,是我们最起码的底线! 以服务为基础,以质量求生存,以技术求发展,成交一个客户多一个朋友!为您提供成都网站设计、成都网站制作、成都网页设计、成都微信小程序、成都网站开发、成都网站制作、成都软件开发、成都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
②.六个关系运算:less
③.三个逻辑运算,分别对应&&、||、!:logical_and
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和set1.使用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.包含头文件
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元起,快前往官网查看详情吧
本文题目:泛型编程风格-创新互联
文章链接:http://azwzsj.com/article/icsec.html