C++ day05(模版与容器)

news2024/12/23 14:56:12

目录

【1】模版 template

1》概念

2》函数模版

3》类模版

【2】容器

1》STL标准模版库

2》容器的概念

3》顺序容器 

1> arrry(C++11)

2> vector

 3> list

4> deque

4》 关联容器

5》迭代器 iterator 


【1】模版 template

1》概念

C++模版可以让类或函数声明一种通用类型,使得函数或类中的某些成员变量或成员变量的参数、返回值在实际上的使用中可以是任何类型。

模版可以让程序员写出与类型无关的代码,是泛型编程的基础。

模版主要分为两种实现方式:

1.函数模版

2.类模版

2》函数模版

#include <iostream>

using namespace std;

// 函数模板
template <class T> //可以是class 也可以是typename
T add(T a,T b)
{
    return a+b;
}

class Dog
{

};

int main()
{
    // 在使用的过程中T可以任何类型
    cout << add(2,3) << endl;
    cout << add(2.2,2.2) << endl;
    cout << add('0','0') << endl;
    // 这套通用算法可能不支持某些类型
    // 错误出现的原因并非不能传参,而是不能计算
    cout << add("aa","aa") << endl; // 错误 const char* 指针不能计算
    Dog d1;
    Dog d2;
    add(d1,d2);//错误,类对象不能计算

    return 0;
}

3》类模版

#include <iostream>

using namespace std;

template <typename T>
class Demo
{
private:
    T value;

public:
    Demo(T value):value(value){}

    T get_value() const
    {
        return value;
    }
};

class MobilePhone
{
private: // 私有:被修饰的成员只能在类内访问
    string brand; // 读写
    string model = "16"; // 只读
    int weight; // 只写

public:
    string get_brand() // getter:读函数
    {
        return brand;
    }

    void set_brand(string b) // setter:写函数
    {
        brand = b;
    }

    string get_model()
    {
        return model;
    }

    void set_weight(int w)
    {
        weight = w;
    }
};

int main()
{
    // 类模板在创建对象时要标注T的具体类型,以便于开辟内存
    Demo<int> d1(1);//T 为 int 类型
    cout << sizeof(d1) << " " << d1.get_value() << endl; // 4 1

    Demo<long> d2(1);//T 为 long 类型
    cout << sizeof(d2) << " " << d2.get_value() << endl; // 4 1

    MobilePhone mp1;
    Demo<MobilePhone> d3(mp1);//T 为 MobilePhone 类型
    cout << sizeof(d3) << endl; // 12

    return 0;
}

类模版声明定义分离时,编写稍微繁琐

#include <iostream>

using namespace std;

template <typename T>
class Demo
{
private:
    T value;

public:
    Demo(T value);
    T get_value() const;
};

template <typename T> //每个函数定义时都需要写上模版的声明
Demo<T>::Demo(T value)
{
    this->value = value;
}

template <typename T>
T Demo<T>::get_value() const
{
    return value;
}

class MobilePhone
{
private: // 私有:被修饰的成员只能在类内访问
    string brand; // 读写
    string model = "16"; // 只读
    int weight; // 只写

public:
    string get_brand() // getter:读函数
    {
        return brand;
    }

    void set_brand(string b) // setter:写函数
    {
        brand = b;
    }

    string get_model()
    {
        return model;
    }

    void set_weight(int w)
    {
        weight = w;
    }
};

int main()
{
    // 类模板在创建对象时要标注T的具体类型,以便于开辟内存
    Demo<int> d1(1);
    cout << sizeof(d1) << " " << d1.get_value() << endl; // 4 1

    Demo<long> d2(1);
    cout << sizeof(d2) << " " << d2.get_value() << endl; // 4 1

    MobilePhone mp1;
    Demo<MobilePhone> d3(mp1);
    cout << sizeof(d3) << endl; // 12

    return 0;
}

【2】容器

1》STL标准模版库

标准模板库(Standard Template Library,STL)是惠普实验室开发的一系列软件的统称。虽说它主要表出现到C++中,但在被引入C++之前该技术就已经存在了很长时间。

STL的代码从广义上讲分为三类:algorithm(算法)、container(容器)和iterator(迭代器),几乎所有的代码都采用了模板类和模板函数的方式,这相比于传统的由函数和类组成的库来说提供了更好的代码重用机会。

2》容器的概念

容器是存储数据的集合,存储的数据元素可以是任何类型,因为容器是模版实现的。容器类对象只能使用栈内存,不支持堆内存。另外,容器类的使用都需要引入对应的头文件。 

3》顺序容器 

顺序容器是一种线性结构的可序群集,但是可以通过或删除(array不支持)等操作改变元素的位置。

1> arrry(C++11)

array比内置数组更加安全和易于使用。

#include <iostream>
#include <array> // 头文件

using namespace std;


int main()
{
    array<int,5> arr; // 创建一个长度为5的int数组
    // 赋值
    arr[0] = 1;
    arr[1] = 2;
    arr[2] = 3;
    arr[3] = 4;
    arr[4] = 5;
    // 修改
    arr.at(2) = 222;
    arr[3] = 333;

//    cout << arr.at(-3248673) << endl; 崩溃

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

    arr.fill(666); // 更改所有元素的值
    for(int i:arr)
        cout << i << " ";
    cout << endl;

    // 迭代器(略)

    return 0;
}

2> vector

vector 内部通过数组实现,但是vector 是可变长的,因此每次长度变化时,内部重新创建数组,能高效的进行随机存取(数组的内存连续),但是不擅长插入删除。

#include <iostream>
#include <vector> // 头文件

using namespace std;

int main()
{
    vector<int> vec1; // 创建一个长度为0的对象
    cout << vec1.empty() << endl; // 1

    vector<int> vec2(5); // 创建一个长度为5的对象
    for(int i=0;i<vec2.size();i++)
        cout << vec2.at(i) << " "; // 0 0 0 0 0

    cout << endl;

    vector<int> vec3(vec2); // 拷贝构造
    for(int i:vec3)
        cout << i << " ";

    cout << endl;

    // 参数1:长度
    // 参数2:默认值
    vector<string> vec4(5,"AAA");
    // 增加元素
    vec4.push_back("BBB"); // 尾插
    // 在第二个位置插入元素
    // begin返回一个迭代器指针,指向第一个元素
    vec4.insert(vec4.begin()+1,"No.2");
    // 在倒数第三个位置插入元素
    // end返回一个迭代器指针,指向最后一个元素的后面
    vec4.insert(vec4.end()-2,"No.-3");

    // 删除数据
    vec4.pop_back(); // 删除最后一个数据
    // 删除第一个数据
    vec4.erase(vec4.begin());
    // 删除倒数第一个数据
    vec4.erase(vec4.end()-1);

    // 删除所有元素
    vec4.clear();

    for(string i:vec4)
        cout << i << " ";
    cout << endl;

    // 迭代器(略)

    return 0;
}

 3> list

list 内部由双向链表实现,内存空间不连续,只能通过迭代器指针访问,不支持下标,但是可以高效的进行插入删除操作,不擅长随机存取。

#include <iostream>
#include <list> // 头文件

using namespace std;

int main()
{
    list<int> lis1; // 创建一个长度为0的对象
    cout << lis1.empty() << endl; // 1

    list<int> lis2(5); // 创建一个长度为5的对象

    cout << endl;

    list<int> lis3(lis2); // 拷贝构造
    for(int i:lis3)
        cout << i << " ";

    cout << endl;

    // 参数1:长度
    // 参数2:默认值
    list<string> lis4(5,"AAA");
    // 增加元素
    lis4.push_back("BBB"); // 尾插
    // 在第二个位置插入元素
    // begin返回一个迭代器指针,指向第一个元素
    lis4.insert(++lis4.begin(),"No.2");
    // 在倒数第三个位置插入元素
    // 存储迭代器指针
    list<string>::iterator iter =  lis4.end();
    // 移动迭代器指针,-2表示向前移动两位
    advance(iter,-2);
    // end返回一个迭代器指针,指向最后一个元素的后面
    lis4.insert(iter,"No.-3");

    // 删除数据
    lis4.pop_back(); // 删除最后一个数据
    // 删除第一个数据
    lis4.erase(lis4.begin());
    // 删除倒数第一个数据
    lis4.erase(--lis4.end());

    // 删除所有元素
//    lis4.clear();

    // 头插
    lis4.push_front("头");
    // 删除第一个元素
    lis4.pop_front();
    // 取出第一个和最后一个元素的引用
    cout << lis4.front() << " " << lis4.back() << endl;

    // 排序(升序)
    lis4.sort();

    for(string i:lis4)
        cout << i << " ";
    cout << endl;

    // 迭代器(略)

    return 0;
}

4> deque

插入删除和随机存取的性能介于 vector 和 list 之间,擅长两端存取,API几乎兼容 vector 和 list。

4》 关联容器

各个元素之间没有严格的顺序关系,但是内部仍然有排序的热点,因此才可以使用迭代器进行遍历。

最常用的关联容器是 map :键值对映射。

 

键(Key)的功能是元素名称,因此常用字符串表示,且具备唯一性;值可以是任何类型,且值可以重复。

#include <iostream>
#include <map> // 头文件

using namespace std;

int main()
{
    map<string,int> ma;
    cout << ma.empty() << endl; // 1
    // 插入数据
    ma["height"] = 180;
    ma["salary"] = 17999;
    ma["salary"] = 18000; // 因为之前有这个键了,变为修改
    ma.insert(pair<string,int>("age",28));
    ma.insert(pair<string,int>("weight",78));
    ma.insert(pair<string,int>("weight",79)); // 之前有此键,不改
    ma["comm"] = 2000;

    cout << ma.size() << endl; // 5

    // 取出元素
    cout << ma["weight"] << endl; // 78
    cout << ma["salary"] << endl; // 18000

    // 判断一个元素是否存在
    map<string,int>::iterator iter =  ma.find("name"); // 拿到迭代器指针
    if(iter == ma.end()) // 没有此键
    {
        cout << "没有name键" << endl;
    }

    // 删除一个元素
    // 返回值表示删除结果
    // ==0:删除失败  >0:删除成功
    int result = ma.erase("age");
    if(result)
    {
        cout << "删除成功" << endl;
    }else
    {
        cout << "删除失败" << endl;
    }

    result = ma.erase("age");
    if(result)
    {
        cout << "删除成功" << endl;
    }else
    {
        cout << "删除失败" << endl;
    }

    ma.clear();
    cout << ma.size() << endl; // 0

    return 0;
}

5》迭代器 iterator 

迭代器是一种特殊的指针,可以遍历所有的容器,常用的迭代器有:

1.iterator  读写迭代器

2.const_iterator 只读迭代器

#include <iostream>
#include <array>
#include <vector>
#include <list>
#include <deque>
#include <map>

using namespace std;

int main()
{
    string s = "fklsdhfjksdhfjksdhjk";

    array<double,5> arr;
    vector<int> vec(5);
    list<int> lis(5);
    deque<int> deq(5);
    for(int i=0;i<arr.size();i++)
    {
        deq[i] = vec[i] = arr[i] = i+1;
        lis.push_back(i+1);
    }

    map<string,int> ma;
    // 插入数据
    ma["height"] = 180;
    ma["salary"] = 18000;
    ma.insert(pair<string,int>("age",28));
    ma.insert(pair<string,int>("weight",78));
    ma["comm"] = 2000;

    // 开始迭代器!
    for(string::const_iterator iter = s.begin();
        iter != s.end();iter++)
    {
        cout << *iter << " ";
    }
    cout << endl;

    for(array<double,5>::iterator iter = arr.begin();
        iter != arr.end();iter++)
    {
        cout << *iter << " ";
    }
    cout << endl;

    for(vector<int>::iterator iter = vec.begin();
        iter!= vec.end();iter++)
    {
        cout << *iter << " ";
    }
    cout << endl;

    for(list<int>::iterator iter = lis.begin();
        iter!= lis.end();iter++)
    {
        cout << *iter << " ";
    }
    cout << endl;

    for(deque<int>::iterator iter = deq.begin();
        iter!= deq.end();iter++)
    {
        cout << *iter << " ";
    }
    cout << endl;

    for(map<string,int>::iterator iter = ma.begin();
        iter!=ma.end();iter++)
    {
        //  通过first和second区分键值
        cout << iter->first << " " << iter->second << endl;
    }

    return 0;
}

今天的分享就到这里结束啦,如果有哪里写的不好的地方,请指正。
如果觉得不错并且对你有帮助的话点个关注支持一下吧!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2200796.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

javacpp调用pdfium的c++动态库

1、.h头文件 2、生成java代码的conf PdfiumDocumentConfigure.java package org.swdc.pdfium.conf;import org.bytedeco.javacpp.annotation.Platform; import org.bytedeco.javacpp.annotation.Properties; import org.bytedeco.javacpp.tools.InfoMap; import org.byte…

网络知识点之—EVPN

EVPN&#xff08;Ethernet Virtual Private Network&#xff09;是下一代全业务承载的VPN解决方案。EVPN统一了各种VPN业务的控制面&#xff0c;利用BGP扩展协议来传递二层或三层的可达性信息&#xff0c;实现了转发面和控制面的分离。 EVPN解决传统L2VPN的无法实现负载分担、…

springboot+vue前后端分离-使用腾讯云服务器部署网站

项目打包 参考链接 CSDN springboot打包 idea默认新建的shell窗口在项目根目录位置&#xff0c;可以看到项目根目录下有mvnw HELP.md log mvnw mvnw.cmd pom.xml src target./mvnw clean package -Dmaven.test…

Kali Linux中安装配置影音资源下载神器Amule

一、Debian系列Linux安装amule命令&#xff1a; sudo apt update sudo apt-get install amule amule-utils 二、配置Amule的要点&#xff1a; 1、首次运行Amule&#xff0c;提示是否下载服务器列表&#xff0c;点击是。 2、搜索选项的类型选择全球&#xff0c;类型的默认选项…

数据恢复与数据取证:Visual NAND Reconstructor 闪存数据恢复工具

天津鸿萌科贸发展有限公司是专业闪存数据恢复工具 VNR (Visual NAND Reconstructor) 的授权代理商。 VNR&#xff08;Visual NAND Reconstructor&#xff09;可视化 NAND 重建工具套件由硬件和软件构成。其中硬件部分包含 NAND 读卡器和一组用于不同 NAND 芯片封装的适配器。读…

LeetCode 48 Rotate Image 解题思路和python代码

题目&#xff1a; You are given an n x n 2D matrix representing an image, rotate the image by 90 degrees (clockwise). You have to rotate the image in-place, which means you have to modify the input 2D matrix directly. DO NOT allocate another 2D matrix and …

序列化流和反序列化流

序列化流 ObjectOutputStream 序列化流/对象操作输出流 包装基本流&#xff0c;属于字节流的一种&#xff0c;负责输出数据。可以把Java中的对象写到本地文件中去。 构造方法&#xff1a; public ObjectOutputStream&#xff08;OutputStream out&#xff09;把基本流包装成高…

【Java 并发编程】解决多线程中数据错乱问题

前言 承接上回&#xff0c;我们已经理解了线程的一些相关操作&#xff0c;本篇内容将会讲到如何去解决线程竞争导致的数据错乱。 前期回顾&#xff1a;线程操作 目录 前言 线程竞争的场景 竞态条件的详解 synchronized 关键字 ReentrantLock 类 线程竞争的场景 概念&#xff1a…

异步场景: promise、async函数与await命令介绍

如果你也对鸿蒙开发感兴趣&#xff0c;加入“Harmony自习室”吧&#xff01;扫描下方名片&#xff0c;关注公众号&#xff0c;公众号更新更快&#xff0c;同时也有更多学习资料和技术讨论群。 在鸿蒙的开发中&#xff0c;我们时常会遇到promise异步场景&#xff0c;有同学反馈说…

Adobe Acrobat Pro和Adobe Acrobat DC有什么区别?

主要区别 Adobe Acrobat Pro&#xff1a; 以单次购买的方式提供&#xff0c;用户需要一次性付费购买&#xff0c;之后即可永久使用该版本。不会频繁更新&#xff0c;通常只在发行新版本时进行更新。 Adobe Acrobat DC&#xff1a; 以订阅方式提供&#xff0c;用户需要每年支付…

《2024 国庆旅游数据洞察:活力与新趋势》

《2024 国庆旅游数据洞察&#xff1a;活力与新趋势》 一、国庆旅游市场整体态势 今年国庆假期&#xff0c;旅游市场的火爆程度令人瞩目。从出行人次来看&#xff0c;嘀嗒出行的国庆顺风出行预测显示&#xff0c;顺风出发高峰日预计为 9 月 29 日&#xff0c;环比 9 月出行峰值…

在Ubuntu 22.04上安装Ollama的两种方式

curl 安装 参考Linux上安装Ollama的官方文档&#xff1a;https://ollama.com/download/linux 在终端执行以下命令即可&#xff1a; curl -fsSL https://ollama.com/install.sh | shdocker 安装 官方 Ollama Docker 镜像可以直接在Docker Hub上进行拉取。 Docker Hub上的ol…

Java 方法的重载

1.重载&#xff1a;在一个类中&#xff0c;方法的函数名相同&#xff0c;但形参不同。 结果&#xff1a; 2&#xff0e;方法重载的规则&#xff1a; &#xff08;1&#xff09;方法名必须相同。&#xff08;例如&#xff1a;重名的人有很多&#xff09; &#xff08;2&#x…

数据库(MySQL):使用命令从零开始在Navicat创建一个数据库及其数据表(二).设置主键自增等特点

前言 在上一节中&#xff0c;主要介绍了 Navicat Premium 17 的使用以及创建一个基础的表格。当时只设置了给数据表补充字段&#xff0c;没有设置给数据表删除字段。现在补充一下。 ALTER TABLE student ADD test int(4); 给名为 student 的数据表添加 test 列&#xf…

正则表达式-“三剑客”(grep、sed、awk)

1.3正则表达式 正则表达式描述了一种字符串匹配的模式&#xff0c;可以用来检查一个串是否含有某种子串&#xff0c;将匹配的子串替换或者从某个串中取出符号某个条件的子串等&#xff0c;在linux中代表自定义的模式模版&#xff0c;linux工具可以用正则表达式过滤文本。Linux…

vavr Java的函数式编程神器-Part1

微信公众号&#xff1a;阿俊的学习记录空间 小红书&#xff1a;ArnoZhang wordpress&#xff1a;arnozhang1994 博客园&#xff1a;arnozhang CSDN&#xff1a;ArnoZhang1994 1. 介绍 Vavr&#xff08;前称 Javaslang&#xff09;是一个为 Java 8 提供的函数式库&#xff0c;…

红外探测算法!!!

一、红外探测的基本原理 红外探测基于红外辐射与物体的热状态之间的关系。物体温度越高&#xff0c;辐射能量越大。红外探测器通过接收物体发出的红外辐射&#xff0c;将其转换为电信号&#xff0c;进而实现对目标的探测和识别。 二、红外探测算法的主要类型 背景差分法&…

[自然语言处理]RNN

1 传统RNN模型与LSTM import torch import torch.nn as nntorch.manual_seed(8)def dm01():参数1&#xff1a;输入向量的维数参数2&#xff1a;隐藏层神经元的个数参数3&#xff1a;隐藏层的层数:return:rnn nn.RNN(5, 6, 1)参数1&#xff1a;句子长度sequence_length参数2&am…

九芯电子NVH/NVF语音芯片OTA升级操作方法

OTA&#xff08;Over-The-Air&#xff09;升级是指通过无线网络远程对设备进行软件升级的过程。对于九芯电子NVH/NVF语音芯片&#xff0c;OTA升级可以通过WiFi模组实现&#xff0c;支持MQTT、HTTP等协议&#xff0c;方便快捷‌。 具体操作步骤如下&#xff1a; 1.进入九芯“智…

计算机毕业设计 基于Django的学生选课系统的设计与实现 Python+Django+Vue 前后端分离 附源码 讲解 文档

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…