NO.7 C++ 模版编程&容器

零蚀


函数模版

  • 函数模版

    当我们不知道要传入和返回的类型的时候我们可以定义一个模版,他可以根据需要来设置自己的类型,它不存在于函数区中,他不会和其他同名函数发生冲突。如果有普通函数,会优先执行普通函数。

    函数模版并不是真正的函数,他只是一个模版,用来生成其满足格式的函数,与他相反对应的是具名函数。

    template <typename T>
    T add(T a,T b){
        return a+b;
    }
    int main() {
    
        std::cout << add(1.0,2.2) << std::endl;
        std::cout << add(11,22) << std::endl;
        return 0;
    }
    

    多种模版类型如下,模版也是支持重载的。

    template <typename T, typename V>
    T add(T a,V b){
        return a+b;
    }
    template <class N, class M>
    N add(M a,N b){
        return a+b;
    }
    int main() {
    
        std::cout << add('c',2.2) << std::endl;
        std::cout << add(11,22) << std::endl;
        return 0;
    }
    
  • 可变参数

    可变参数有两种类型,一个是initializer_list要求可变参数的类型都必须一致,而省略号的则不具备这些限制。

    省略号

    #include <stdarg.h>
    // ...不能统计到个数,要自己传个数
    int add(int num, ...){
        va_list vl;
        va_start(vl,num);
        int sum=0;
        for(int i=0;i<num;i++){
            sum+=va_arg(vl,int);
        }
    
    
        va_end(vl);
        return sum;
    }
    int main() {
    
        std::cout << add(5,1,2,3,4,5) << std::endl;
        return 0;
    }
    

    initializer_list

    /**
     *
     * @param initializer_list<可变参数的参数> list
     * @return
     * list 提供了start和end
     */
    void add(initializer_list<int> list){
        
    
        for(auto p=list.begin();p<list.end();p++){
            cout << *p << endl;
        }
    }
    int main() {
    
        add({1,2,3,4,5});
        return 0;
    }
    
  • 可变参数的函数模版

    在模版函数里,可变参数是传递过来的是参数包形式,通常获取数据的方式是递归,每调用一次,参数就会少一个,最后将参数全部拿出来。

    int func(){
        return 0;
    }
    
    template <typename ... T>
    int func(int a,T ... b ){
        //这里的...a是任意的复合类型的参数包。
        //拆包
        cout << a << endl;
        func(b...);
        return 0;
    }
            
    int main() {
    
        func(1,2,3);
        return 0;
    }
    

    func由于必须有一个int a的实参,所以如果不写一个空参的函数,会由于没有检测到空参会报错。

    递归图解

    函数执行完会走出栈操作。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ONOstN8Z-1584030461613)(media/15839999286425/15840212961698.jpg)]

    参数包解包的操作

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sWLEYtbU-1584030461614)(media/15839999286425/15840231376015.jpg)]


容器

  • 顺序容器

    顺序容器是在容器内部,元素摆放是有顺序的,通常vector已经能满足大部分开发。这些数组item的存储空间都是连续的,当增删的时候为了保持数组的顺序,所以要移动顺序,所以增删慢查询快(vector也是),列表相反。

    容器描述
    string与vector相似,尾部插入删除数度快
    array固定大小的数组,支持快速的随机访问,不能添加和删除
    vector可变大小数组,支持快读访,在尾部之外的地方插入/删除速度慢
    deque双向队列,支持快速的随机访问,两端的插入删除速度快
    forward单向链表,只支持单项顺序访问,插入和删除快,查询慢
    list与单项列表不同,它是双向列表,其他一样
  • 迭代器

    所有的容器都有迭代器,迭代器可以对内容间接访问。

    vector<int> vec{1,3,4,5};
    auto begin=vec.begin();
    auto end=vec.end();
    // * 作用域base的返回值,用于解引用
    cout << *(begin.base()+1) << endl;
    // * 是operator* 迭代器的运算符重载
    cout << *(begin+1) << endl;
    // 获取最后一个也可以最后一个,end 表示末尾的 \0
    cout << *(end-1) << endl;
    
  • 关联容器

    根据关键字来索引item的,c++中有两个关联容器:map & set

    构建pair

    #include <utility>
    // 键值对的类
    pair<string,int> p;
    p.first="云梦栏";
    p.second=11;
    pair<string,int> p1{"开了",10};
    cout << p.first << endl;
    

    构建map

    map是一对一的关系,一个键对应一个值,如果想要一对多就要用到multimap,它允许一对多,它们都定义子在include

    #include <map>
    // 这里不能map map1("",11)这样会类型匹配错误,构造里默认是char类型
    // 源码两个参数构造:map(const key_compare& __comp, const allocator_type& __a)
    map<string,int> map1;
    //插入
    map1.insert({"科技",11});
    int age= map1["科技"];
    cout << age << endl;
    // 遍历
    for (auto i = map1.begin(); i != map1.end(); ++i) {
        // 这里的->也是运算符的重载
        cout << i->first << ":" << i->second << endl;
    }
    cout << map1.size() << endl;
    
    

    构建set

    set是简单集合,并且元素不能重复,当知识想知道一个值是否存在的时候,set是最为有用的,set为不可重复的容器,multiset为可重复的容器。系统会自动给set里的元素进行排序,set中的元素不能直接改变,内部是采用了一种非常高效的的平衡检索二叉树:红黑树,也称RB树,RB树的统计性要好于一般的平衡二叉树。

    set<int> s;
    s.insert(1);
    s.insert(1);
    s.insert(2);
    for (auto i = s.begin(); i != s.end(); i++) {
        cout << *i << endl; 
    }
    // 1,2
    

🔗 前言
🔗 C++ 高级列表
🔗 NO.1 C++ 基础
🔗 NO.2 C++ 指针
🔗 NO.3 C++ 特殊函数
🔗 NO.4 C++ 重载&继承&lambda
🔗 NO.5 C++ 虚函数&智能指针
🔗 NO.6 C++ I/O
🔗 NO.8 C++ 常用函数&线程
🔗 NO.9 C++ QT 入门
🔗 NO.10 C++ QT 绘制&自定义组合控件
🔗 NO.11 C++ QT 绘制

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

零蚀zero eclipse

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值