C++泛型编程总结(一)

目录:

  1.STL的组成

    2.指针的算术运算

    3.泛型find()的实现&泛型指针iterator的作用

    4.常用泛型算法汇总

    5.所有容器的通用操作

    6.顺序容器vector,list,deque的插入和删除

       vector iterators incompatible错误避免与原因分析


 1.STL的组成

    (1)容器container:vector\list\set\map\pair……
    (2)泛型算法generic algorithm:find()\sort()\replace()\merge()……

2.指针的算术运算
    array[2]  ==  *(array+2)
    若array的第一个元素的地址1000,那么array+2 != 1002,因为必须把“指针所指的类型”考虑进去
    例:int为4byte(32bit,1个机器字长),那么array+2 == 1008

3.泛型find()的实现&泛型指针iterator的作用
    要求:1.自适应类型int,string等。2.自适应array,vector
<span style="font-size:14px;">template<typename elemType>
inline elemType* begin(const vector<elemType>& vec)
{ return vec.empty() ? 0 : &vec[0]; }

template<typename elemType>
const elemType* find(const elemType* first,  //返回的是地址,不加const可能会被修改
    const elemType *last,const elemType& value) 
{
    if(!first || !last)
        return 0;
    for(;first != last; ++first)
        if(*first == value)
            return first;
    return 0;
}
//调用
int ia[8] = {1,1,2,3,5,8,13,21};
const int* pi=find(ia,ia+8,ia[3]);
//vector
find(begin(svec),end(svec),search_value)</span>
附注:使用iterator,可以find()能够自适应到vector和list两种不同容器
           iterator作为一种泛型指针,用于隐藏不同容器间的差异,是
实现泛型算法的基础
    要求3:自适应不同容器的泛型find()
template<typename IteratorType,typename elemType>
IteratorType find(IteratorType first,IteratorType last,
    const elemType& value)
{
    for(;first != last;++first)
        if(*first == value)
            return first;
    return last;
}
int main()
{
    int ia[8] = {1,1,2,3,5,8,13,21};
    int *pi=find(ia,ia+8,5);
    if(pi != pi+8)
        cout<<"找到了"<<endl;
    vector<int> vec(ia,ia+8);
    vector<int>::iterator iter =find(vec.begin(),vec.end(),22);
    if(iter != vec.end())
        cout<<"找到了"<<endl;
   return 0;
}

4.常用泛型算法(Essential附录B)
int ia[8] = {1,1,2,3,5,8,13,21};
int ia2[9] = {1,1,2,3,5,8,13,21,24};
list<int> ilist(ia,ia+8)
以下,ia相当于ilist.begin(),ia+8相当于ilist.end()
加“*”表示可重构运算类型,重构方式如下:
class Even
{
public:
    bool operator()(int val)
    { return !(val%2); }
};
ires = count_if(ia,ia+8,Even())
class Twiceover
{
public:
    bool operator()(int val1,int val2)
    { return val1==val2/2 ? true : false; }
}
iter=adjacent_find(ia,ia+8,Twiceover())
搜索:<algorithm>iter
find(ia,ia+8,value) 若找到,返回其迭代器;否则,返回end(), 附find_end()
find_if(ia,ia+8,LessThanVal(val)) 一找到,就返回迭代器                              
*adjacent_find(ia,ia+8) 返回第一组相邻重复元素中第一个元素的迭代器
count(ilist.begin(),ilist.end,value) 返回容器中与value相等的元素个数         
*count_if(ia,ia+8,bind2nd(less<int>(),10)) 返回"<10"的元素个数
*binary_search(ia,ia+8,value) 在"<"排列的容器中找value,返回bool          
find_first_of() 搜索某些元素首次出现的地点
search()在序列1中搜索序列2,返回序列2起始处的迭代器    
排序&次序整理:<algorithm>
merge(ia,ia+8,ia2,ia2+9,result.begin()) 合并已排序序列,放置与result
partial_sort() 局部排序
partition() 局部总和
random_shuffle(vec.begin(),vec.end()) 随机重排
reverse(ilist.begin(),ilist.end())颠倒元素次序
rotate(ia,ia+3,ia+8)旋转结果:{3,5,8,13,21,1,1,2}
sort(ia,ia+8) 从小到大排序
复制、删除、替换:<algorithm>
copy(ilist.begin(),ilist.end,listCopy.begin())复制  copy_backward逆向复制
remove(vec.begin(),vec.end(),0) 移除元素但不删除                                     
*remove_if(vec.begin(),vec.end(),Even()) 返回删除后的有效迭代器end()
replace(vec.begin(),vec.end(),oldval,newval) 取代某个元素                       
repace_if(vec.begin(),vec.end(),bind2nd(less<int>(),10),new)有条件取代
swap() 交换
unique(vec.begin,vec.end()) 将重复元素折叠所编使其唯一,与remove类似 
fill(ia,ia+8,value)改填元素为value,fill_n(ia,n,value)只设n个元素值为value
关系:<algorithm>
*equal(ia,ia+7,ia2),若等长部分元素相等,返回true,ia2多的元素不管
includes(ia2,ia2+9,ia,ia+8) 若ia的元素都在ia2中,返回true,ia和ia2已排序
mismatch()
max(ia[0],ia[1]) 返回两元素中最大值
max_element(ia,ia+8) 返回最大值的迭代器
distance(ia,iter) 返回两个迭代器的距离,例如iter和和ia的距离
数值:<numeric>
*accmulate(ia,ia+8,0) 返回元素累加结果,“0”为指定初值                         
adjacent_difference(ia,ia+8,iresult.begin()) 相邻元素差额
  {0,1,1,2,3,5,8} -> {0,1,0,1,1,2,3} 保留第0位,其他:该位-前一位
partial_sum()                                                                                      
*inner_product(ia,ia+8,ia2,0) 内积,对应相乘再相加
集合:<algorithm>
set_union(ia,ia+8,ia2,ia2+9,ia3) 并集 {0,1,2,3}+{0,2,4,6}={0,1,2,3,4,6}
set_difference(ia,ia+8,ia2,ia2+9,ia3) 差集,集合1有,但集合2木有的元素,抽出来排序放入集合3 。集合1和2都排好序
较重要的泛型
int ia[] = {0,1,0,2,0,3,0,4,0,5};
vector<int> vec(ia,ia+10);
vec_iter = remove(vec.begin(),vec.end(),0)  //0是要删除的元素
//remove()操作之后、erase()操作之前的vector内容:{1,2,3,4,5,3,0,4,0,5}
//要保留的元素都被向前复制。
vec.erase(vec_iter,vec.end());//erase()操作后的vector内容:1,2,3,4,5

//数组不易改变大小,所以不适用remove,而要用remove_copy()
int ia2[5]
remove_copy(ia,ia+10,ia2,0)  //得到ia2:1,2,3,4,5

5.所有容器的通用操作
  • equality==   inequality!=   
  • assignment=   
  • empty()
  • size()
  • clear()
  • begin()   end() 返回迭代器
  • insert() 插入
  • erase() 删除

6.顺序容器vector,list,deque的插入和删除
定义:
  • vector<int> ivec(32)  //大小32,默认每个值为0,    适用于随机访问
  • listM<string> slist(16,"unassigned")  //大小16,每个字符赋值“unassigned”    适用于插入删除操作频繁
插入删除:
  • 通用:push_back(),pop_back()
  • list和deque还有:push_front(),pop_front()
  • 通用:front()  back()  返回最前端或最后端值
vector的删除erase和插入insert,注意避免vector iterators incompatible错误,插入删除后要赋值
#include<iterator>
#include<algorithm>
#include<vector>
template <typename T>
void DeleteVector(vector<T> &data, T key)
{
    //vector<T>::iterator itr = data.begin();
    //while(itr != data.end())
    //{
    //    if(*itr == key){
    //        itr=data.erase(itr); //注意要赋值itr
    //        return;
    //    }
    //    else
    //        ++itr;
    //}
    vector<T>::iterator iter = find(data.begin(),data.end(),key);
    if(iter != data.end())
        iter=data.erase(iter);
}
template <typename T>
void InsertVector(vector<T> &data, T key)
{
    vector<T>::iterator itr = data.begin();
    while (itr != data.end())
    {
        if(*itr < key)
            itr=itr+1;
        else{
            itr=data.insert(itr,key); //注意赋值itr
            break;
        }
    }
    if(itr == data.end())
        data.push_back(key);
    return;
}
如果itr在插入或删除后没有赋值,可能出现vector iterators incompatible的错误
分析原因:
  • 如果插入后没有修改 itr,就在下方比较 itr 和 data.end() ,那么就出现错误;
  • 问题出现在insert之后,vector的链表改变,新插入的元素不在iterator所引用的地址;
  • 正确的做法是将insert()返回的插入元素的iterator赋给itr;
  • 同理erase()也存在同样的问题,erase一个元素后,后续元素不一定移动到iterator所引用的位置。
其他引发该错误的原因有:
  • 空Vector问题。不允许引用空vector的begin迭代器,因为vector是空的,自然不会有第一个项目,使用也会引发vector iterators incompatible。vector.clear()后,不能用vector.begin()
  • vc2005 对于迭代器的匹配是非常严格的,通常这种错误是因为两个不同的迭代器操作同一个 vector,或者是因为迭代器在遍历vector时,vector的链表改变了,就会引发这种错误,比如vector在遍历的途中,别的位置push_back()一个元素,这时迭代器就失效了,导致错误。可以使用临界区互斥访问。





  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值