2023/9/14 -- C++/QT

news2024/11/27 16:59:53

作业:

仿照Vector实现MyVector,最主要实现二倍扩容

#include <iostream>

using namespace std;

template <typename T>
class MyVector
{
private:
    T *data;
    size_t size;
    size_t V_capacity;
public:
    //无参构造
    MyVector():data(nullptr),size(0),V_capacity(0) {
        //cout<<"MyVector::无参构造"<<endl;
    }
    //有参构造
    MyVector(int count,T val){
        size = count;
        V_capacity = count;
        data = new T[count];
        for(int i = 0;i < count;i++){
            data[i] = val;
        }
        //cout<<"MyVector::有参构造"<<endl;
    }
    //析构函数
    ~MyVector(){
        delete [] data;
        data = nullptr;
        //cout<<"MyVector::析构函数"<<endl;
    }
    // 定义迭代器类
    class MyIterator {
    private:
        T* ptr;
    public:
        //有参构造
        MyIterator(T* p):ptr(p){
            //cout<<"MyIterator::有参构造"<<endl;
        }
        // *重载
        T& operator*()const {
            return *ptr;
        }
        // 前置++重载
        MyIterator& operator++() {
            ++ptr;
            return *this;
        }
        // 后置++重载
        MyIterator operator++(int) {
            MyIterator temp = *this;
            ++ptr;
            return temp;
        }
        // 前置--重载
        MyIterator& operator--() {
            --ptr;
            return *this;
        }
        // 后置--重载
        MyIterator operator--(int) {
            MyIterator temp = *this;
            --ptr;
            return temp;
        }
        // ==重载
        bool operator==(const MyIterator& other) const {
            return ptr == other.ptr;
        }
        // !=重载
        bool operator!=(const MyIterator& other) const {
            return ptr != other.ptr;
        }
    };
    //begin 函数  返回第一个元素的迭代器
    MyIterator begin() {
        return MyIterator(data);
    }
    //end 函数  返回最末元素的迭代器(注:实指向最末元素的下一个位置)
    MyIterator end() {
        return MyIterator(data + size);
    }
    //assign 函数  对MyVector中的元素赋值
    void assign(size_t num, const T &val ){
        for(int i = 0;i < num;i++){
            data[i] = val;
        }
        cout<<"assign 函数"<<endl;
    }
    //at 函数  返回指定位置的元素
    T at(int pos){
        if(pos < 0 || pos >= size){
            throw int(1);                 //抛出异常
        }
        return data[pos];
    }
    //back 函数 返回最末一个元素
    T back(){
        return data[size-1];
    }
    //capacity 函数  返回vector所能容纳的元素数量
    size_t capacity(){
        return V_capacity;
    }
    //clear 函数  清空所有元素
    void clear(){
        size = 0;
    }
    //empty 函数  判空
    bool empty(){
        return size == 0;
    }
    //front 函数  返回第一个元素
    T front(){
        return data[0];
    }
    //pop_back 函数  移除最后一个元素
    void pop_back(){
        if(empty()){
            throw int(2);           //抛出异常
        }
        size--;
    }
    //push_back 函数  在MyVector最后添加一个元素
    void push_back(const T& value) {
        if (size == V_capacity) {
            // 扩容逻辑
            size_t newCapacity = (V_capacity == 0)?1:V_capacity * 2;
            T* newData = new T[newCapacity];
            for(int i = 0;i < static_cast<int>(size);i++){
                newData[i] = data[i];
            }
            delete[] data;
            data = newData;
            V_capacity = newCapacity;
        }
        data[size++] = value;
    }
    //size 函数  返回Vector元素数量的大小
    size_t get_size(){
        return size;
    }
};

int main()
{
    MyVector<int> V1(5,2);
    cout<<"V1的第一个元素 = "<<V1.front()<<endl;
    cout<<"V1的最末一个元素 = "<<V1.back()<<endl;
    cout<<"V1的capacity = "<<V1.capacity()<<endl;
    cout<<endl;
    cout<<"********************************************************"<<endl;
    cout<<endl;

    V1.push_back(8);
    V1.push_back(5);
    V1.push_back(7);
    V1.push_back(6);
    cout<<"V1的第一个元素 = "<<V1.front()<<endl;
    cout<<"V1的最末一个元素 = "<<V1.back()<<endl;
    cout<<"V1的capacity = "<<V1.capacity()<<endl;
    cout<<"V1的size = "<<V1.get_size()<<endl;
    cout<<endl;
    cout<<"********************************************************"<<endl;
    cout<<endl;

    int *p = NULL;
    MyVector<int>::MyIterator q(p);
    cout<<"当前容器内的元素:";
    for(q = V1.begin();q != V1.end();q++){
        cout<< *q <<"\t";
    }
    cout<<endl;
    cout<<endl;
    cout<<"********************************************************"<<endl;
    cout<<endl;

    V1.pop_back();
    cout<<"V1的最末一个元素 = "<<V1.back()<<endl;
    V1.pop_back();
    cout<<"V1的最末一个元素 = "<<V1.back()<<endl;
    V1.pop_back();
    cout<<"V1的最末一个元素 = "<<V1.back()<<endl;
    cout<<"V1的size = "<<V1.get_size()<<endl;
    cout<<endl;
    cout<<"********************************************************"<<endl;
    cout<<endl;

    V1.clear();
    cout<<"V1的size = "<<V1.get_size()<<endl;

    return 0;
}

效果图:

一、异常处理

【1】异常概念

C++中的异常指的是在程序运行过程中出现的问题,没有任何语法错误,存在逻辑问题

【2】异常处理

  1. throw ----->抛出异常,抛出异常一定在异常发生之前
  2. try ····catch ----->捕获异常并进行异常处理

总结:

  1. 抛出异常一定在发生异常之前
  2. try···catch中可以存放所有可能发生异常的代码,只要有一条语句抛出异常,try后面的语句都不会执行
  3. 异常可以只有数据类型,也可以及有数据类型也有值
  4. catch可以通过数据类型,获取到异常的结果并使用if进行判断,如果每种异常抛出的都是不同的数据类型,catch中就无需定义变量
  5. 如果同种数据类型的异常有多个值,要依次根据值来判断异常的情况
  6. throw抛出异常往往被调函数的位置,try···catch往往在主调函数内处理异常
#include <iostream>
using namespace std;

void fun(int a,int b)
{
    //throw 数据类型(值)
    //数据类型:指定抛出异常的类型,便于接收
    //值:针对不同的异常情况,给出不同的值,处理异常时使用

    //在执行语句之前先对可能发生异常的位置进行判断
    if(b==0)
    {
        throw double(1);
    }
    if(b==3)
    {
        //函数内抛出了两个double类型的异常,分别返回不同的值
        throw int(2);
    }
    if(b==2)
    {
        throw double(2);
    }

    cout << a/b << endl;
}


//处理异常一般在主函数内
//try···catch处理异常
int main()
{
    //tyr尝试接收异常,try内可以放多条语句,
    //有一条语句抛出异常后,后面都不会执行
    try
    {
        //try去接收所有可能的异常
        fun(4,2);
        fun(2,1);
        fun(3,3);

    }
    //由于函数中,只有一个double类型的异常,所以可以直接对异常的类型进行判断
    catch (double a)    //如果double后面加变量名,变量会获取到异常的结果
    {
        if(a==1)
            cout << "除数为0" << endl;
        if(a==2)
            cout << "除数为2是一个测试" << endl;
    }
    catch (int)
    {
        cout << "除数为3是一个测试" << endl;
    }
    fun(3,1);


    cout << "1" << endl;
}

二、using的第三种用法

#include <iostream>

//using namespace std;
using std::string;
class A
{
public:
    string name;
};
class B:public A
{
protected:
    using A::name;
};
namespace P {
    string n1;
}

//给命名空间重命名
//namespace 新的名字 = 旧的名字
//新名字和旧名字都能用
namespace O = P;
int main()
{
    using std::cout;
    using std::endl;

    typedef int a;    //后面可以直接使用a定义int类型的变量
    //C++11支持的
    using  INT  = int;   //后面可以直接使用INT定义int类型的变量
    INT num1 = 100;
    cout << num1 << endl;
    P::n1 = "helo";
    O::n1 = "hi";
    cout << O::n1 << endl;

    return 0;
}

三、类型转换

【1】隐式强转

以及和C中一致的显式强转

#include <iostream>
using namespace std;

int main()
{
    float num1 = 2.3;
    int num2 = num1;    //发生了隐式的强制类型转换
    
    //C中的显式强制类型转换
    double num3 = (double)num2;
    cout << num2 << endl;
    return 0;
}

【2】C++中支持的强制类型转换

  1. const_cast,取消常属性,取消常量指针的属性
  2. static_cast,和平时使用时发生强转用法一致,几乎支持所有类型间的强转
  3. dynamic_cast,发生在父子类指针间的转换,如果转换失败,会返回空地址
  4. reinterpret_cast,给类型重新赋值,不常用,不会检查数据类型匹配问题
#include <iostream>
using namespace std;

class A
{
    string name;
public:
    virtual void show()
    {
        cout << name << endl;
    }
};

class B:public A
{
    mutable int age;
public:
    void fun()const
    {
         age = 90;
    }
    void show()
    {
        cout << &age << endl;
    }    
};

int main()
{
    //定义了一个常量num1
    const int num1 = 90;
    int *p;   //定义了一个指针变量
    p = const_cast<int *>(&num1);   //使用const_cast让指针指向const修饰的变量的地址
    *p = 12;
    cout << *p << endl;
    //mutable关键也可以取消常属性

    //static_cast适用于几乎所有的强制类型转换
    char var = 'a';
    int num2;
    //int num2 = (int)var;
    num2 = static_cast<int>(var);
    cout << num2 << endl;
    
    A* p1 = new B;    //父类指针指向子类的空间
    A* p2 = new A;    //父类指针指向父类的空间
    //B* p3 = static_cast<B*>(p2);  p2指向父类的空间,但是static_cast可以强转成功
    B* p3 = dynamic_cast<B*>(p2);
    //使用了dynamic_cast,可以实现多态情况下,可以实现父子类指针的转换
    //如果父类指针没有指向子类的空间,返回值为0
    cout << "父类指针指向父类的空间" << p2 << endl;
    cout << "子类的指针" << p3 << endl;
    B* p4 = reinterpret_cast<B*>(p2);
    cout << "父类指针指向父类的空间" << p2 << endl;
    cout << "子类的指针" << p4 << endl;
    
    char *str = "hello";
    int a = reinterpret_cast<int>(str);
    cout << a << endl;
    //p3->show();

    return 0;
}

四、lambda表达式

应用场合:

想要使用匿名的、临时的函数,并且还需要获取外部变量时

  1. lambda(λ)表达式,是C++11支持的
  2. lambda表达式,用于实现轻量级的匿名函数
  3. 定义:[]()mutable->返回值{函数体}; --->结果一般使用auto接收
[捕获列表](参数列表)mutable->返回值{函数体};
1、[=]:对所有变量按值捕获
   [&]:对所有变量按引用捕获
   [a,b]:对a和b按值捕获
   [&a,&b]:对a和b按引用捕获
    //[=,&a]:对除a外的变量值捕获,a按引用捕获
    //[&,a]:对除a外的变量按引用捕获,a按值捕获

2、参数列表:和普通函数的参数一致,就是传参数到函数中
3、mutable可以写也可以不写:
如果不写mutable,在lambda表达式中不能修改按值捕获的变量的值,按引用捕获的不受影响
4、lambda实现的匿名函数的返回值
5、函数体就是匿名函数的实现
#include <iostream>
using namespace std;

int main()
{
    int a = 90,b = 7,c,d,e;
    cout << "a=" << a << endl;
    cout << "b=" << b << endl;
    cout << "--------------------" << endl;
    //使用lambda表达式,实现主函数内变量值的交换
    //[=]:对所有变量按值捕获
    //[&]:对所有变量按引用捕获
    //[a,b]:对a和b按值捕获
    //[&a,&b]:对a和b按引用捕获
    //[=,&a]:对除a外的变量值捕获,a按引用捕获
    //[&,a]:对除a外的变量按引用捕获,a按值捕获

    //lambda表示式,使用auto类型获取
    auto fun = [&,a]()mutable->void{ int temp;
                                      temp = a;
                                      a = b;
                                      b = temp;};
    fun();
    //使用lambda实现求最大值
    auto max = [=]()->int{  if(a>b)
                             return a;
                            else
                              return b; };
    cout << max() << endl;
    return 0;
}

五、STL标准模板库

C++ Standard Template Library

C++ 标准模板库(STL)

C++ STL (Standard Template Library标准模板库) 是通用类模板和算法的集合,它提供给程序员一些标准的数据结构的实现如 queues(队列), lists(链表), 和 stacks(栈)等.

C++ STL 提供给程序员以下三类数据结构的实现:

  • 顺序结构
    • C++ Vectors
    • C++ Lists
    • C++ Double-Ended Queues
  • 容器适配器
    • C++ Stacks
    • C++ Queues
    • C++ Priority Queues
  • 联合容器
    • C++ Bitsets
    • C++ Maps
    • C++ Multimaps
    • C++ Sets
    • C++ Multisets

【1】Vector

Vector的底层实现,就是线性表

Vectors 包含着一系列连续存储的元素,其行为和数组类似。访问Vector中的任意元素或从末尾添加元素都可以在常量级时间复杂度内完成,而查找特定值的元素所处的位置或是在Vector中插入元素则是线性时间复杂度。

需要手动导入头文件#include

1、求vetcor容器的大小:
size_type capacity();
capacity() 函数 返回当前vector在重新进行内存分配以前所能容纳的元素数量.
2、添加元素
void push_back( const TYPE &val );
push_back()添加值为val的元素到当前vector末尾
3、求容器的真实大小
size_type size();
size() 函数返回当前vector所容纳元素的数目 
4、给容器中的元素赋值
void assign( size_type num, const TYPE &val );
赋num个值为val的元素到vector中.这个函数将会清除掉为vector赋值以前的内容.
5、访问容器中的元素
TYPE at( size_type loc );
at() 函数 返回当前Vector指定位置loc的元素的引用. at() 函数 比 [] 运算符更加安全, 因为它不会让你去访问到Vector内越界的元素.
6、清空容器中的元素
void clear();
clear()函数删除当前vector中的所有元素.
7、判空函数
bool empty();
如果当前vector没有容纳任何元素,则empty()函数返回true,否则返回false.例如,以下代码清空一个vector,并按照逆序显示所有的元素:
8、返回起始位置的引用
TYPE front();
front()函数返回当前vector起始元素的引用
9、返回最后一个位置的引用
TYPE back();
back() 函数返回当前vector最末一个元素的引用.    
10、返回起始元素的迭代器
iterator begin();
begin()函数返回一个指向当前vector起始元素的迭代器.
11、返回末尾下一个位置的迭代器
iterator end();
end() 函数返回一个指向当前vector末尾元素的下一位置的迭代器.
注意,如果你要访问末尾元素,需要先将此迭代器自减1.
12、指定位置的插入,由于没有提供返回指定位置迭代器,需要在第一个元素的迭代器上运算
iterator insert( iterator loc, const TYPE &val );
在指定位置loc前插入值为val的元素,返回指向这个元素的迭代器, 
13、移除最后一个元素
void pop_back();
pop_back()函数删除当前vector最末的一个元素,
14、构造函数
vector( input_iterator start, input_iterator end );
迭代器(start)和迭代器(end) - 构造一个初始值为[start,end)区间元素的Vector(注:半开区间). 

【2】List

list的底层实现是一个双向链表

主要功能

1、头插
void push_front( const TYPE &val );
push_front()函数将val连接到链表的头部。
2、最大容量
size_type max_size();
max_size()函数返回链表能够储存的元素数目
3、元素个数
size_type size();
size()函数返回list中元素的数量。
4、排序
void sort();
给链表中的元素排序,默认是升序
5、判空
bool empty();
empty()函数返回真(true)如果链表为空,否则返回假。

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

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

相关文章

数据结构ArrayList

ArrayList的顶级理解 1.ArrayList的简介2.ArrayList的使用3.ArrayList的构造4.ArrayList常见操作5.ArraList的遍历5.1 普通for循环5.2 增强for循环5.3 迭代器循环 6.ArrayList的扩容机制 1.ArrayList的简介 ***ArrayList是以泛型方式实现的&#xff0c;使用时必须要先实例化Arr…

4.zigbee开发,串口的应用,ADC采集

一。串口应用 0.在c盘的协议库中 拷贝sampleApp 1.串口的初始化 1.找到初始化 2.在这个函数中加入函数初始化 //串口初始化halUARTCfg_t uart_Config;uart_Config.configuredTRUE;uart_Config.flowControlFALSE;uart_Config.baudRateHAL_UART_BR_115200;HalUARTOpen(HAL_UART_…

laravel-admin联动选择展示时ueditor样式错乱

问题 录入内容时&#xff0c;根据资源类型&#xff0c;展示不同的需要录入的内容&#xff0c;很常见的功能&#xff0c;但是在切换时&#xff0c;编辑器一直出不来&#xff0c;如图&#xff1a; 代码如下&#xff1a; $form->radio(type, 资源类型)->when(2, function…

Kubenetes之Pod详解

Pod详解 一、Pod基础概念1.概念2.在Kubrenetes集群中Pod有如下两种使用方式3.pause容器使得Pod中的所有容器可以共享两种资源4.kubernetes中的pause容器主要为每个容器提供以下功能5.Kubernetes设计这样的Pod概念和特殊组成结构有什么用意6.通常把Pod分为两类 二、容器的分类&a…

sql中怎么查books表下面的内容

要查询 books 表中的所有内容&#xff0c;你可以使用以下 SQL 语句&#xff1a; USE bookmanagement; -- 选择数据库 SELECT * FROM books; -- 查询books表中的所有内容如果你使用的是命令行界面 (mysql 客户端) 来操作数据库&#xff0c;可以直接在命令提示符中输入上述命令…

微信公众号迁移步骤

公众号账号迁移的作用是什么&#xff1f;只能变更主体吗&#xff1f;长期以来&#xff0c;由于部分公众号在注册时&#xff0c;主体不准确的历史原因&#xff0c;或者公众号主体发生合并、分立或业务调整等现实状况&#xff0c;在公众号登记主体不能对应实际运营人的情况下&…

算法通过村第七关-树(递归/二叉树遍历)白银笔记|递归实战

文章目录 前言1. 深入理解前中后序遍历从小到大递推分情况讨论&#xff0c;明确结束条件组合出完整的方法&#xff1a;从大到小 画图推演 总结 前言 提示&#xff1a;没有客观公正的记忆这回事&#xff0c;所有的记忆都是偏见&#xff0c;都是为自己的存活而重组过的经验。--国…

LeetCode(力扣)452. 用最少数量的箭引爆气球Python

LeetCode452. 用最少数量的箭引爆气球 题目链接代码 题目链接 https://leetcode.cn/problems/minimum-number-of-arrows-to-burst-balloons/description/ 代码 class Solution:def findMinArrowShots(self, points: List[List[int]]) -> int:if len(points) 0:return 0…

固定资产管理中净值怎么算

在资产管理的领域中&#xff0c;我们经常听到“净值”这个词。然而&#xff0c;对于许多人来说&#xff0c;净值的概念仍然模糊不清。本文将试图揭示固定资产管理的净值计算方法&#xff0c;并提供一些创新的观点。  我们需要明确什么是净值。在财务术语中&#xff0c;净值是…

一同走进Linux的“基操”世界

一同走进Linux的“基操”世界 众所周知&#xff0c;Linux是一个开源、免费的操作系统&#xff0c;其稳定性、安全性、处理多并发能力已经得到业界的认可&#xff0c;可以说&#xff0c;Linux现在就像是一个“当红明星”&#xff0c;其实力赢得了大多数人的赞同&#xff0c;流量…

机器学习——贝叶斯(三种分布)/鸢尾花分类分界图/文本分类应用

0、前言&#xff1a; 机器学习中的贝叶斯的理论基础是数学当中的贝叶斯公式。这篇博客强调使用方法&#xff0c;至于理论未作深究。机器学习中三种类型的贝叶斯公式&#xff1a;高斯分布&#xff08;多分类&#xff09;、多项式分布&#xff08;文本分类&#xff09;、伯努利分…

2000-2021年上市公司数字化转型数据(MDA报告词频、文本统计)

2000-2021年上市公司数字化转型数据&#xff08;MD&A报告词频、文本统计&#xff09; 1、时间&#xff1a;2000-2021年 2、来源&#xff1a;上市公司NB 3、范围&#xff1a;上市公司 4、指标&#xff1a;包括人工智能技术、大数据技术、云计算技术、区块链技术、数字技…

【深度学习】 Python 和 NumPy 系列教程(十三):Matplotlib详解:1、2d绘图(上):折线图、散点图、柱状图、直方图、饼图

目录 一、前言 二、实验环境 三、Matplotlib详解 0、绘图风格 1、2d绘图类型 0. 设置中文字体 1. 折线图&#xff08;Line Plot&#xff09; 2. 散点图&#xff08;Scatter Plot&#xff09; 3. 柱状图&#xff08;Bar Plot&#xff09; 4. 直方图&#xff08;Histogr…

【千万别上当】揭秘又一个割韭菜的项目:明星网红直播切片项目

今天在某乎浏览内容&#xff0c;看到一篇文章《我做了10个某音号&#xff0c;不拍视频&#xff0c;不直播&#xff0c;光靠剪辑明星素材月入8K&#xff0c;给缺钱的朋友推荐一个无脑赚Q的自媒体项目》&#xff0c;点击进去一看&#xff0c;洋洋洒洒估计有一两万字&#xff0c;过…

对西安交大轴承数据集XJTU-SY_Bearing_Datasets进行读取和处理:

对西安交大轴承数据集XJTU-SY_Bearing_Datasets进行读取和处理&#xff1a; 读取交大全寿命数据并显示 1.python 读取任意一个工况里的任意一个轴承数据的任意文件csv #读取数据集的CSV文件并显示 import csv import matplotlib.pyplot as pltdef csv_read(CSV_data,CSV_numb…

JavaScript事件流:深入理解事件处理和传播机制

&#x1f3ac; 岸边的风&#xff1a;个人主页 &#x1f525; 个人专栏 :《 VUE 》 《 javaScript 》 ⛺️ 生活的理想&#xff0c;就是为了理想的生活 ! 目录 引言 1. 事件流的发展流程 1.1 传统的DOM0级事件 1.2 DOM2级事件和addEventListener方法 1.3 W3C DOM3级事件 …

JRedis的基本操作,基本数据类型操作

Redis的基本数据类型&#xff1a; stringhashlistsetzset {public static void main(String[] args) {Jedis jedis new Jedis("127.0.0.1", 6379);// stringjedis.set("hello", "word");String hello jedis.get("hello");System.o…

Packet Tracer安装、汉化

Packet Tracer是一款由思科系统开发的网络模拟器&#xff0c;用于学习和实验网络配置、协议和拓扑结构。它提供了一个虚拟的网络环境&#xff0c;让用户能够在不需要实际硬件设备的情况下进行网络实验和模拟。 安装 Packet Tracer的安装注册&#xff1a;在Packet Tracer软件上…

Acwing.885 求组合数l

题目 给定n组询问&#xff0c;每组询问给定两个整数a&#xff0c;b&#xff0c;请你输出C mod (10&#xff0b;7)的值。 输入格式 第—行包含整数n。 接下来n行&#xff0c;每行包含—组a和b。 输出格式 共n行&#xff0c;每行输出一个询问的解。 数据范围 1≤n ≤ 1000…

基于深度学习网络的烟雾检测算法matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2022a 3.部分核心程序 .........................................................................% 预处理训练数…