[C++]七 STL编程-模板、容器


标准模板库(Standard Template Library,STL)是惠普实验室开发的一系列软件架构的统称,后续被引入到C++中
在STL编程中,几乎所有的代码都是用采用了模板技术来进行设计,相比于传统编程,这种设计弱化参数类型的概念,使代码具有更好的通用性和重用的机会。
STL编程这种弱化了类型的方式也完全符合泛型编程的概念。

模板

C++中模板是支持“参数化多态”的工具,就是让类或者函数声明为一种通用类型,使得类中的某些成员变量、成员函数的参数、返回值等在实际的使用中可以是任意的类型。模板可以让程序员写出与类型无关的代码,是泛型编程的基础。
模板主要有两种形式:
函数模板
类模板

函数模板

函数模板可以使一个函数的参数和返回值支持通用类型,使此函数专注于算法设计

#include <iostream>

using namespace std;

//模板声明
template <class T>
T add(T a, T b)
{
    return a+b;
}

class Dog
{
public:
    //运算符重载,仅仅为了让语法通过
    friend Dog operator +(const Dog& d1, const Dog& d2);
};

Dog operator +(const Dog&d1, const Dog& d2)
{
    Dog d;
    return d;
}

int main()
{
    string s1 = "AAA";
    string s2 = "aaa";
    cout << add(s1, s2) << endl;
    cout << add(1, 2) << endl;

    Dog d1;
    Dog d2;
    add(d1, d2);
    return 0;
}

类模板

#include <iostream>

using namespace std;

//模板声明
template <class T> //class也可以使用typename
class Test
{
private:
    T value; //T类型的value(在主函数中定义类型)

public:
    Test(T v):value(v){}
    T get_value() const
    {
        return value;
    }
    void set_value(T v)
    {
        value = v;
    }
};

int main()
{
    //创建一个T类型为int的对象
    Test<int> t1(123);
    t1.set_value(321);
    cout << t1.get_value() << endl;

    //创建一个T类型为string的Test对象
    Test<string> t2("abc");
    t2.set_value("xyz");
    cout << t2.get_value() << endl;
    
    return 0;
}

类模板声明定义分离

#include <iostream>

using namespace std;

template <class T>
class Test
{
private:
    T value;
public:
    Test(T v);

    T get_value() const;
    void set_value(T v);
};

template <class T>//每个类都需声明
Test<T>::Test(T v):value(v){};//构造函数的定义

template <class T>
T Test<T>::get_value() const
{
    return value;
}

template <class T>
void Test<T>::set_value(T v)
{
    value = v;
}
//主函数和类模板相同

容器

容器是用来存储数据的集合,数据元素可以是任何类型
容器的分类:
顺序容器:string字符串
array数组(C++11)
vector向量
list列表
deque队列
关联容器:map键值对映射
multimap多重键值对映射
容器类的自动申请和释放内存,无需new和delete操作
所有容器使用时都需要引入对应的头文件;string除外
顺序容器中各个元素之间是呈现线性有序分布的,而关联容器没有严格的物理顺序

array数组

此类型是C++11引入的新的容器类型,用于代替传统数组。除了array以外还有顺序容器中各个元素位置并不是固定的,可以通过删除或插入等操作改变后面元素位置
使用时添加#include头文件

//创建一个长度为5的int数组对象
    array<int,5> arr = {1,2,3,4};
    //赋值
    arr[0] = 100;
    arr.at(1) = 200;

    //遍历
    for(int i = 0;i < arr.size();i++)
    {
        cout << arr.at(i) << " ";
    }
    cout << endl;

    //填充所有元素
    arr.fill(6);
    for(int i:arr)
    {
        cout << i << " ";
    }
    cout << endl;

vector向量

vector是除string外的所有顺序容器中最常用的一种,vector内部使用数组实现,各元素之间的内存是连续的,尽管支持动态长度,但vector更擅长随机存取,不擅长插入和删除操作
头文件!头文件!头文件!#include
创建并判断是否为空:

vector<int> vec1; //创建一个元素为空的向量对象
    cout << "是否为空:" << vec1.empty() << endl; 

增删改及遍历:

//创建初始元素为5个2的常量对象
    vector<int> vec3(5,2);
    //向后追加
    vec3.push_back(4);
    //在第二位置插入元素5
    // 参数1:插入位置,begin函数返回值迭代器指针,这个指向第一个元素的位置
    // 参数2:插入的元素
    vec3.insert(vec3.begin()+1,5);
    // 在倒数第二个位置插入元素666
    // 此时可以使用end函数获取迭代器指针,此迭代器指针指向的是当前的最后一个元素的后面
    vec3.insert(vec3.end()-1,666);
    //删除第三个元素
    vec3.erase(vec3.begin()+2);
    //删除倒数第三个位置的元素
    vec3.erase(vec3.end()-3);
    //修改第三个元素为3
    vec3.at(2) = 3;
    //修改第二个元素为222
    vec3[1] = 222;
    //for-each遍历
    for(int i:vec3)
    {
        cout << i << " ";
    }
    cout << endl;

list列表

list内部使用双向链表实现,各元素之间的内存不是连续的,虽然元素之间呈线性分布,但是不支持下标操作,只能使用迭代器指针操作。能高效地进行插入删除操作,随机存取的效率较低
list增删改查
头文件!头文件!头文件!#include

 list<int> lis;//创建一个元素为空的列表对象
    cout << "是否为空:" << lis.empty() << endl;
    list<int> lis2(5);//创建一个初始长度为5的列表对象
    //创建初始元素为5个2的列表对象
    list<int> lis3(5,2);
    //向后追加
    lis3.push_back(8);
    //向前追加
    lis3.push_front(666);
    //获取最后一个元素和第一个元素
    cout << lis3.back() << " " << lis3.front() << endl;
    //第二个位置插入元素123
    //迭代器指针使用自增或自减来操作
    lis3.insert(++lis3.begin(),123);
    //在第三个位置插入元素333
    //1.先获得头部的迭代器指针对象
    list<int>::iterator iter = lis3.begin();
    //2.使用固定的函数来移动
    advance(iter,2);//后移两下
    //插入元素
    lis3.insert(iter,333);
    //取出第三个元素
    iter = lis3.begin();
    advance(iter,2);
    cout << *iter << endl;
    //删除倒数第一个元素
    iter = lis3.end();
    lis3.erase(--iter);
    //修改第一个元素值111
    iter = lis3.begin();
    *iter = 111;
    //排序
    lis3.sort();
    //因为不支持下标,所以不支持for循环
    //for-each
    for(int i:lis3)
    {
        cout << i <<" ";
    }
    cout << endl;
    //清空
    lis3.clear();
    //大小
    cout << lis3.size() << endl;

deque队列

对于接口,deque基本兼容vector和list的接口
从性能上来说,无论插入删除,还是随机存取,其性能都介于vector和list之间,但是由于队列的特性其首位两端的操作比较高效

map键值对映射

map是最常用的一种关联容器,容器之间的各元素之间没有严格的物理顺序,但是其内部仍有某种顺序进行存储,所以支持迭代器遍历
map指的是键值对映射,键key表示元素名称,值value表示元素的数值,一个键绑定一个数据,因此又称键值对
通常键使用的数据类型是字符串,而值的类型根据实际情况制定。键是不可重复的,而值可以重复
头文件!头文件!头文件!#include

	//创建一个元素为空的map对象
    map<string,int> map1;
    cout << "是否为空:" << map1.empty() << endl;
    //插入数据
    map1["heiget"] = 100;
    map1["age"] = 20;
    map1["age"] = 25;//修改元素
    map1["weiget"] = 77;
    map1["sal"] = 4500;
    map1.insert(pair<string,int>("id",100001));

    //取出某个键对应的值
    cout << map1.find("age")->second << endl;
    //取出前判断键值对是否存在
    if(map1.find("name") != map1.end())
        cout << map1.find("name")->second << endl;
    else
        cout << "没有name键值对!" << endl;
    
    //删除元素
    if(map1.erase("sal"))
        cout << "删除sal键值对成功!" << endl;
    else 
        cout << "删除sal键值对失败!" << endl;

    //清空
    map1.clear();
    cout << map1.size() << endl;

迭代器

所有容器类型都支持迭代器遍历,iterator是读写迭代器,const_iteratoe是只读迭代器迭代器遍历的性能是最高的

cout << endl << "string关键字" << endl;
    string s = "klfneanfaknfen";
    for(string::iterator iter = s.begin();iter != s.end();iter++)
    {
        cout << *iter << " ";
    }
    cout << endl;

    cout << endl << "array数组" << endl;
    array<string,6> arr = {"fdfea","awfdwa","af","aef","aefeg"};
    for(array<string,6>::iterator iter = arr.begin();
        iter != arr.end();iter++)
    {
        cout << *iter << " ";
    }
    cout << endl;

    cout << endl << "vector向量" << endl;
    vector<double> vec(5,1.23);
    for(vector<double>::iterator iter = vec.begin();
        iter != vec.end();iter++)
    {
        cout << *iter << " ";
    }
    cout << endl;

    cout << endl << "list列表" << endl;
    list<double> lis(5,3.14);
    for(list<double>::iterator iter = lis.begin();
        iter != lis.end();iter++)
    {
        cout << *iter << " ";
    }
    cout << endl;

    cout << endl << "deque队列" << endl;
    deque<double> deq(5,13.14);
    for(deque<double>::iterator iter = deq.begin();
        iter != deq.end();iter++)
    {
        cout << *iter << " ";
    }
    cout << endl;

    cout << endl << "map键值对" << endl;
    map<string,string> map1;
    map1["name"] = "Jason";
    map1["job"] = "salesman";
    map1["dept"] = "RD";
    for(map<string,string>::iterator iter=map1.begin();
        iter!=map1.end();iter++)
    {
        cout << iter->first << " " << iter->second << endl;
    }
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值