首页 > 编程语言 >C++_day5

C++_day5

时间:2024-11-05 22:47:25浏览次数:3  
标签:cout 迭代 int day5 iter C++ include 模板

目录

1. 模(mú)板 template(掌握)

1.1 概念

1.2 函数模板

1.3 类模板

2. 容器

2.1 STL标准模板库(熟悉)

2.2 容器的概念(掌握)

2.3 顺序容器

2.3.1 array(C++11)(熟悉)

2.3.4 deque(掌握)

2.4 关联容器(掌握)

2.5 迭代器 iterator(掌握)


    本章节主要讲解泛型编程,泛型编程(Generic Programming)最初提出时的动机很简单直接:发明一种语言机制,能够帮助实现一个通用的标准容器库。所谓通用的标准容器库,就是要能够做到,比如用一个List类存放所有可能类型的对象这样的事;泛型编程让你编写完全一般化并可重复使用的算法,其效率与针对某特定数据类型而设计的算法相同。

1. 模(mú)板 template(掌握)

1.1 概念

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

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

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

  • 函数模板
  • 类模板

1.2 函数模板

#include <iostream>

using namespace std;

// 函数模板
template <class T>
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;
}

1.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);
    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;
}

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

#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. 容器

2.1 STL标准模板库(熟悉)

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

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

2.2 容器的概念(掌握)

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

    下面是本次学习的容器类型:

2.3 顺序容器

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

2.3.1 array(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.3.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;
}

2.3.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;
}

2.3.4 deque(掌握)

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

代码略。

2.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;
}

2.5 迭代器 iterator(掌握)

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

  • iterator

读写迭代器

  • 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;
}

标签:cout,迭代,int,day5,iter,C++,include,模板
From: https://blog.csdn.net/weixin_63791423/article/details/143532552

相关文章

  • C++:AVL树
    目录AVL树概念AVL树的实现AVL树的节点AVL树的插入AVL树的平衡调整右单旋左单旋左右双旋右左双旋完整的插入函数AVL树的查找AVL树的验证验证有序验证平衡完整代码AVL树概念AVL树是一种具有特殊性质的二叉搜索树,AVL树的左右子树也都是AVL树,且左右子树的高度差......
  • C++中的各种锁
    在多线程开发中,经常会遇到数据同步,很多情况下用锁都是一个很好的选择。C++中常用的锁主要有下面几种:互斥锁(std::mutex)这是最基本的一种锁。它用于保护共享资源,在任意时刻,最多只有一个线程可以获取该锁,从而访问被保护的资源。当一个线程获取了互斥锁后,其他试图获取该锁的线程会......
  • ROS机器人编程<六>:了解ROS系统及使用VScode实现话题通信(C++)
    目录ROS中基本的通信机制:一、话题通信:1.话题通信定义与基本概念2.核心要素3.工作流程4.消息接口与数据类型二、vscode实现话题通信三、C++实现话题通信 要求:编写发布订阅实现,要求发布方以10HZ(每秒10次)的频率发布文本消息,订阅方订阅消息并将消息内容打印输出1.在......
  • c++:智能指针
    文章目录前言一、内存泄漏1.1内存泄漏的定义1.2内存泄漏的常见原因1.3内存泄漏的危害二、智能指针的用法和模拟实现2.1RAII2.1.1RAII的工作原理2.1.2RAII的优点2.2智能指针的原理和设计思路2.3智能指针的种类和特点2.3.1std::auto_ptr2.3.2std::unique_ptr2.3......
  • 什么是C++模板,有哪些类型的模板?
    模板C++模板是一种强大的语言特性,允许开发者编写与类型无关的代码,从而实现代码的复用和灵活性。通过模板,可以定义函数和类,具体实现将由具体的类型实例化决定。函数模板函数模板(FunctionTemplates):函数模板用于定义一个通用的函数,该函数可以接受任意类型的参数。通过使用模......
  • c++知识及编译调试
    文章目录c++知识指针查找内存模型引用函数编译调试1.编译选项2.静态库和动态库3.gdb调试代码1.通讯录c++知识指针常量(的)指针constint*p=&a;指针指向可改,指向的值不可改。指针常量int*constp=&a;指针不能改,指向的值可改。查找unordered_setit!=uset.e......
  • C++20 STL CookBook 4:使用range在容器中创建view
    目录rangeviewrange_adaptor的三个概念以std::string和std::string_view为例子初次入手补充ranges的一些操作rangeviewrange_adaptor的三个概念新的范围库是C++20中更重要的新增功能之一。它为过滤和处理容器提供了新的范例。范围为更有效和可读的代码提供了简......
  • (分享源码)计算机毕业设计必看必学 上万套实战教程手把手教学JAVA、PHP,node.js,C++、pyth
    摘要信息化社会内需要与之针对性的信息获取途径,但是途径的扩展基本上为人们所努力的方向,由于站在的角度存在偏差,人们经常能够获得不同类型信息,这也是技术最为难以攻克的课题。针对校园疫情大学生防控出入系统等问题,对校园疫情大学生防控出入系统进行研究分析,然后开发设计......
  • C++——用指向指针的指针的方法对5个字符串排序并输出。
    没注释的源代码#include<iostream>#include<string.h>usingnamespacestd;voidsort(char**p);intmain(){  constintm=20;  char**p,*pstr[5],str[5][m];  for(inti=0;i<5;i++)    pstr[i]=str[i];  cout<<"pleaseinput5......
  • 计算机毕业设计项目推荐,高校学生社团管理系统 00498(开题答辩+程序定制+全套文案 )上万
    摘要随着计算机科学技术的日渐成熟,人们已经深刻地认识到了计算机在各个领域中发挥的功能的强大,计算机已经进入到了人类社会发展的各个领域,并且发挥着十分重要的作用。目前学校学生社团的管理是一项系统而复杂的工作,它需要一个团队互相配合、分工协作。在该领域,传统的手工存取......