C++要点细细梳理(下)(内存分配、异常处理、template和文件读写)

news2024/10/7 1:21:48

4. 类动态内存分配

4.1 C语言动态内存分配:malloc和free

在这里插入图片描述

4.2 C++动态内存分配:new和delete

  • 思考:定义一个对象和定义一个普通变量有何区别?
    • 普通变量:分配足够空间即可存放数据
    • 对象:除了需要空间,还要构造/析构
  • 类比:
    • malloc/free:租用一个仓库->存放货物 ->货物卖完 ->退租走人
    • new/delete:租一块地 ->修建大厦 (构造)->到期不用了 ->爆破拆除善后(析构) ->地归原主
      在这里插入图片描述
  • 调用默认构造函数,那么new+类名即可
  • 调用带参数的构造函数,那么new+类名(参数)
    在这里插入图片描述

4.2.1 new[ ]与delete[ ]运算符

  • new[ ]:申请空间并批量构造对象数组,返回首元素指针
  • delete[ ]:批量析构对象数组并释放空间,只能用于new[ ]出来的指针
    在这里插入图片描述

4.2.2 malloc/free和new/delete的区别

在这里插入图片描述

4.2.3 虚析构函数

4.2.3.1 内存泄漏和内存溢出
  • 内存溢出

  • 内存泄漏
    在这里插入图片描述

4.2.3.2 虚析构函数

在这里插入图片描述
在这里插入图片描述

4.3 例题

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

5. 异常处理

5.1 异常与bug

在这里插入图片描述
在这里插入图片描述

异常与bug的区别

  • 对于Bug:程序员可控,越用心进行开发/走查/测试,Bug越少
  • 对于Exception:程序员不可控,需要代码中设置针对异常情况的保护措施
    • 网络应用:网络连通性、时延等不可控因素对于程序来说是异常
    • 游戏:玩家打出极限操作、突破预先设置的情况是异常
    • 数据分析:数据缺失值、未曾料想的特殊值等情况是异常
    • 等等
      • 除以0异常(不除以0就是正常的)
      • 空指针异常(指针不空就是正常的)
      • 数组越界异常(数组不越界就是正常的)
      • int溢出异常(int不太大就是正常的)

总之,程序正确编译了,也能按照既定逻辑执行功能,但是遇到了合法范围外的数据导致程序失去确定性而中断就是异常

5.2 异常处理

异常会导致程序失去确定性,不知道怎么继续下去,于是有异常保护:

  • 异常保护:引导程序继续走下去,再不济也要做好收尾工作,体面结束
    在这里插入图片描述

5.2.1 throw和try-catch

  • throw:使用throw语句主动立即抛出一个异常对象(但不一定throw才抛异常,如n/0)
    • throw抛出异常后会直接去执行catch对应的语句,原来异常语句下面的不会执行
  • try:保护一个语句块,后跟一个或多个catch块。try块中抛出异常不会立刻中止程序而是寻找catch处理
  • catch:捕获指定异常并进行处理,处理完不会再返回try块,直接离开try-catch继续执行

5.2.2 多个catch,捕获顺序:从详到略

在这里插入图片描述

5.2.3 多层函数调用中抛出异常

在这里插入图片描述

  • 当前层函数无法处理异常就结束此层,在稍外层继续抛出该异常,如果还是无法解决继续向更外层抛出异常,直到到达某层函数能够处理该异常,处理完毕后继续执行处理该异常的函数调用层

5.2.4 函数异常限定符

在这里插入图片描述

5.3 C++标准异常类

  • 虽说我们可以手动throw,抛出什么都可以,但一些常见的程序错误是C++自身抛出的(如除以零)
  • C++根据错误分类根据预设了一系列标准异常,定义在<exception>中
  • 它们以父子类层次结构组织,都在名字空间 std 下

5.3.1 自定义异常类

  • 自定义异常类通常继承自std:exception,并重写一些方法,比如what()
  • 通常在自己编写的程序中会根据业务需求自定义异常类
    在这里插入图片描述

5.4 例题

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

6. 模板

6.1 模板与泛型思想

6.1.1 函数重载为了实现代码复用做出的努力与不足

在这里插入图片描述

6.1.2 模板编程的目的

  • 回顾:从函数 ->函数重载 ->面向对象 ->继承/多态 ->… 核心目的?
    • 代码复用
  • 但以上技术仍然是类型依赖的,需要为不同类型进行相应的实现,如函数重载
  • 即“数据类型”信息是一个超参数,代码逻辑依赖这个超参数信息
  • 模板编程:类型参数化,将类型信息也视作一个普通参数,使代码逻辑与类型信息分离

在这里插入图片描述

6.2 模板函数

  • 用模板函数对不同类型变量进行自定义的拼接相加
    • template 关键字:表明接下来定义一个模板
    • typename 关键字:表明该模板参数是一个类型名——>模板参数可以不是同一个类型
    • T1、T2:是两个类型形式参数,是类型占位符
  • 于是在myAdd函数中就可以用T1和T2指代数据类型,编写代码逻辑
    在这里插入图片描述

模板函数实例化

在这里插入图片描述
在这里插入图片描述

  • 如果传入不支持类型的参数,将会报编译错误

模板类型推断

在这里插入图片描述

模板参数可以用于返回值

在这里插入图片描述

6.3 模板类

在这里插入图片描述

非类型的模板参数

在这里插入图片描述

模板类的声明与定义不可分离

  • 普通类可以模块化:在.h中声明,在.cpp 中定义(实现)
  • 但模板类不可以这样操作,必须声明同时+定义,为什么?
  • 因为编译器无法事先知道类型占位符T是什么,所以必须同时写

6.4 例题

  • 模板的核心思想:类型参数化,不依赖数据类型来编写程序逻辑
  • 模板可用于函数和类的编写:模板函数和模板类
  • template:声明模板,typename:定义模板的类型参数
    在这里插入图片描述
    在这里插入图片描述

7. 文件读写流

7.1 文件读写流

  • 回顾:cin 和 cout 叫做标准输入输出流对象,其机制类似一条河流
  • 事实上,文件I0和使用cin/cout没有本质区别,标准I0只是文件I0的一个特例
  • 文件输入输出流就是这条河流的来源/终点是一个文件

从标准IO到文件IO

  • 现在我们知道cout是一个对象而<<是运算符重载,含义实际上是 cout.插入(“hello”
  • cout 是标准输出流对象因此输出到控制台,如果换成文件输出流对象,就实现了往文件输出,输入流同理
    在这里插入图片描述

文件IO:打开->读/写->关闭

在这里插入图片描述

文件IO:fstream

  • 读文件要用ifstream对象,写文件要用ofstream对象,能不能就用一个流对象,又能读又能写?
  • std::fstream
    在这里插入图片描述
#include <iostream>
#include <fstream>
int main() {
    std::ifstream fin;
    std::ofstream fout;
    fin.open("input.txt",std::ios::in);
    fout.open("output.txt",std::ios::out);

    if (fin.is_open()==false||fout.is_open()==false){
        std::cout<<"Error"<<std::endl;
        return 0;
    }
    std::string name;
    int id;
    float score;

    while (fin.eof()==false){
        fin>>name>>id>>score;
        fout<<id<<" "<<name<<" "<<score<<std::endl;
    }

    fin.close();
    fout.close();

    return 0;
}

7.2 二进制文件读写

  • 思考:通过文本文件存储整数123456789需要多少空间?
  • 在文本文件中,将被存放成字符串“123456789”,共占9个字节
  • 但它本来是个int,只占4字节呀!直接把这4字节写入文件就好了
  • 二进制文件:将数据在内存中的实际存储内容直接写入到文件中,读取时需要知道存储和理解的格式
  • 文本文件:将数据作为一串字符逐一输出到文件中,读取时再按照ASCII码逐字符解读为文本
    在这里插入图片描述
#include <iostream>
#include <fstream>
int main() {
    std::ofstream  fout("data.bin",std::ios::out|std::ios::binary);
    if (!fout.is_open()){
        std::cerr << "Error opening file" << std::endl;
        return 1;
    }
    int a = 10;char b = 'a';;float c = 3.14;
    fout.write(reinterpret_cast<char*>(&a),sizeof(a));
    fout.write(reinterpret_cast<char*>(&b),sizeof(b));
    fout.write(reinterpret_cast<char*>(&c),sizeof(c));
    fout.close();

    std::ifstream fin;
    fin.open("data.bin",std::ios::in|std::ios::binary);
    if (!fin.is_open()){
        std::cerr << "Error opening file" << std::endl;
        return 1;
    }
    int a1;char b1;float c1;
    fin.read(reinterpret_cast<char*>(&a1),sizeof(a1));
    fin.read(reinterpret_cast<char*>(&b1),sizeof(b1));
    fin.read(reinterpret_cast<char*>(&c1),sizeof(c1));
    std::cout << a1 << std::endl << b1 << std::endl << c1 << std::endl;
    fin.close();
    
    return 0;
}

7.3 输出格式控制——流操作算子

  • 在C语言中,通过printf()/fprintf()函数的格式控制符控制输出的格式
  • 而在C++中,文件被封装成了流对象,控制流对象的格式,就能控制输出的格式
  • 通过往流对象中插入流格式控制符控制流对象的输出格式
  • 如希望控制输出小数时保留小数点后两位:
    在这里插入图片描述

常用的流格式控制符

在这里插入图片描述
在这里插入图片描述

7.4 例题

  • 文件在C++中以流对象的形式存在,通过流对象读写文件
  • 文件输入流:ifstream文件输出流:ofstream文件读写流:fstream
  • 流对象可以构造同时打开文件,也可以先定义,再调用open打开

在这里插入图片描述

  • 打开文件时要注意使用正确的相对路径或绝对路径
  • 操作流对象之前,要通过其is open 方法判断是否打开成功

在这里插入图片描述
在这里插入图片描述

  • 读文件时,通过流对象的 eof()方法判断是否已经读到文件尾了
  • eof即end of file
    在这里插入图片描述
  • 通过头文件中的流操作算子控制输出格式

在这里插入图片描述

  • 以二进制模式读写文件将直接拷贝实际存储内容,需要自行编码解码

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

8. 番外:C与C++

C和C++是两种非常相关的编程语言,它们之间存在许多关联,但也有很多显著的差异。

关联:

  1. 起源:C++是C语言的一个超集,也就是说,几乎所有的C语言代码都可以直接在C++中编译和运行。C++的创造者Bjarne Stroustrup在设计C++时,主要的目标之一就是提供一个“更好的C”,这意味着C++保持了C语言的许多特性,并增加了许多新的特性。
  2. 基础语法:C和C++的基本语法非常相似,包括变量声明、条件语句、循环语句等。
  3. :许多C语言的库在C++中仍然可用,尽管C++也提供了许多新的库和功能。

异同:

  1. 类型系统:C++是一种强类型语言,提供了更复杂的类型系统,包括类和对象,而C语言主要基于函数和指针。
  2. 面向对象:C++是一种面向对象的语言,支持类、继承、封装和多态等概念。而C语言主要是面向过程的。
  3. 异常处理:C++提供了异常处理机制,而C语言没有内置的异常处理机制,通常通过错误码和错误处理函数来处理错误。
  4. 模板:C++支持模板,这使得用户可以创建泛型函数和类,提高了代码的重用性。而C语言没有模板的概念。
  5. 运算符重载:C++允许用户重载运算符,以支持自定义类型的特殊运算。而C语言不支持运算符重载。

  1. 内存管理:在C和C++中,程序员都需要直接管理内存,包括分配和释放。这可能会导致内存泄漏等问题,需要程序员小心处理。
  2. 跨平台性:C和C++都是跨平台的语言,可以在多种操作系统和硬件平台上运行。
  3. 性能:由于C和C++都接近硬件,且没有运行时的解释或虚拟机开销,因此它们通常都能提供很高的性能。

总的来说,C和C++在许多方面都非常相似,但C++提供了更多的功能和特性,使得程序员可以编写更复杂、更灵活的程序。然而,这也增加了C++的学习曲线和复杂性。选择使用哪种语言通常取决于项目的具体需求和开发团队的技能。

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

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

相关文章

windows下部署mongoDB

目录 1. 下载zip安装包并解压&#xff1a;Download MongoDB Community Server | MongoDB 2. 在解压后的文件夹中新建文件夹data及下级文件夹db和log 3. 新建一个mongod.cfg文件&#xff0c;并配置以下内容 4. 在cmd中启动mongodb&#xff0c;并进行验证 5. 部署到本地服务器…

物联网实战--驱动篇之(二)Modbus协议

目录 一、modbus简介 二、功能码01、02 三、modbus解析 四、功能码03、04 五、功能码05 六、功能码06 七、功能码16 一、modbus简介 我们在网上查阅modbus的资料发现很多很杂&#xff0c;modbus-RTU ASCII TCP等等&#xff0c;还有跟PLC结合的&#xff0c;地址还分1开…

WCH恒沁单片机-CH32V307学习记录2----FreeRTOS移植

RISC-V 单片机 FreeRTOS 移植 前面用了 5 篇博客详细介绍了 FreeRTOS 在 ARM Cortex-M3 MCU 上是如何运行的。 FreeRTOS从代码层面进行原理分析系列 现在我直接用之前的 RISC-V MCU 开发板子&#xff08;CH32V307VCT6&#xff09;再次对 FreeRTOS 进行移植&#xff0c;其实也…

《图解Vue3.0》- 调试

如何对vue3项目进行调试 调试是开发过程中必备的一项技能&#xff0c;掌握了这项技能&#xff0c;可以很好的定义bug所在。一般在开发vue3项目时&#xff0c;有三种方式。 代码中添加debugger;使用浏览器调试&#xff1a;sourcemap需启用vs code 调试&#xff1a;先开启node服…

Android APP加固利器:深入了解混淆算法与混淆配置

Android APP 加固是优化 APK 安全性的一种方法&#xff0c;常见的加固方式有混淆代码、加壳、数据加密、动态加载等。下面介绍一下 Android APP 加固的具体实现方式。 混淆代码 使用 ipaguard工具可以对代码进行混淆&#xff0c;使得反编译出来的代码很难阅读和理解&#xff…

VMwear桥接网络正确配置+静态IP设置

1.桥接网络配置 很多时候在VMware安装完虚拟机之后&#xff0c;会发现配置的桥接网络没有起作用&#xff0c;如果是Linux下输入ifconfig发现只有ipv6的地址而没有ipv4&#xff0c;说明没有桥接没有启用成功&#xff0c;需要按照以下方式来设置 在VMware的左上角打开编辑&#…

注解式 WebSocket - 构建 群聊、单聊 系统

目录 前言 注解式 WebSocket 构建聊天系统 群聊系统&#xff08;基本框架&#xff09; 群聊系统&#xff08;添加昵称&#xff09; 单聊系统 WebSocket 作用域下无法注入 Spring Bean 对象&#xff1f; 考虑离线消息 前言 很久之前&#xff0c;咱们聊过 WebSocket 编程式…

Nuxt 3 项目中配置 Tailwind CSS

官方文档&#xff1a;https://www.tailwindcss.cn/docs/guides/nuxtjs#standard 安装 Tailwind CSS 及其相关依赖 执行如下命令&#xff0c;在 Nuxt 项目中安装 Tailwind CSS 及其相关依赖 npm install -D tailwindcss postcss autoprefixerpnpm install -D tailwindcss post…

字符迁移.

3.字符迁移【算法赛】 - 蓝桥云课 (lanqiao.cn) 问题描述 小蓝最近获得了一个长度为N 的字符串S&#xff0c;他对它爱不释手。 小桥为了考验小蓝对字符串的处理能力&#xff0c;决定给他提出一个挑战&#xff0c;她会进行 Q次操作&#xff1a; 每次操作给定三个整数 l , r , k …

Vue3调试

如何对vue3项目进行调试 调试是开发过程中必备的一项技能&#xff0c;掌握了这项技能&#xff0c;可以很好的定义bug所在。一般在开发vue3项目时&#xff0c;有三种方式。 代码中添加debugger;使用浏览器调试&#xff1a;sourcemap需启用vs code 调试&#xff1a;先开启node服…

夯实智慧新能源数据底座,TiDB Serverless 在 Sandisolar+ 的应用实践

本文介绍了 SandiSolar通过 TiDB Serverless 构建智慧新能源数据底座的思路与实践。作为一家致力于为全球提供清洁电力解决方案的新能源企业&#xff0c;SandiSolar面临着处理大量实时数据的挑战。为了应对这一问题&#xff0c;SandiSolar选择了 TiDB Serverless 作为他们的数据…

PostgrerSQL基本使用与数据备份

前言 上篇了解了 PostgrerSQL 数据库的部署PostgreSQL关系型数据库介绍与部署-CSDN博客&#xff0c;本篇将继续就其基本操作、备份与还原内容做相关介绍。 目录 一、数据库的操作 1. 本机登录 2. 开启远程登录 2.1 开放远程端口 2.2 编辑配置文件 2.3 修改配置密码 2.…

基于单片机高压输电线路微机保护系统设计

**单片机设计介绍&#xff0c;基于单片机高压输电线路微机保护系统设计 文章目录 一 概要二、功能设计三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机高压输电线路微机保护系统设计是一个涉及电力系统继电保护的复杂工程。该系统主要利用单片机作为控制核心&…

【深度学习】海洋生物数据集,图片分类

文章目录 任务描述数据收集数据处理模型训练指标评测web app代码和帮助 任务描述 收集9种以上的海洋生物图片&#xff0c;然后基于深度学习做一个分类模型&#xff0c;训练完成后&#xff0c;分类模型就可以对未知图片进行分类。 在之后随便传一张图片&#xff0c;分类模型就…

MySQL 50 道查询题汇总,足以巩固大部分查询(附带数据准备SQL、题型分析、演示、50道题的完整SQL)

目录 MySQL 50 道查询题&#xff0c;足以巩固大部分查询数据准备&#xff1a;创建表sql添加表数据sql 50道查询题目汇总01 - 05 题&#xff1a;1、查询 “01” 语文成绩比 “02” 数学成绩高的学生的信息及课程分数2、查询 "01语文课程"比"02数学课程"成绩…

【前端】JavaScript(概念+语法+形式+变量+数组+函数+作用域)

文章目录 JavaScript一、JavsScript概念1.JavaScript的开发方向2.JavaScript和CSS、HTML的关系3.JavaScript运行过程4.JavaScript的组成 二、JavaScript的语法1.JS的书写形式1.行内式2.内嵌式3.外部式4.注释5.输入输出1.prompt和alert2.输出: console.log 2.变量的使用1.创建变…

如何使用CSS构建一个瀑布流布局

如何使用CSS构建一个瀑布流布局 瀑布流布局是一种常见的网页布局方式&#xff0c;其中元素以不同的大小排列&#xff0c;且行与列之间没有不均匀的间隙。在瀑布流布局中&#xff0c;即使某一行或列中的元素较短&#xff0c;下一个元素也会占据空间。 如何实现瀑布流布局 实现…

双连通分量算法

1. 连通图概念 连通图&#xff1a;无向图任意两点之间存在通路。 强连通&#xff1a;有向图&#xff08;前提&#xff09;中&#xff0c;任意两点都有至少一条通路&#xff0c;则此图为强连通图。 弱连通图&#xff1a;将有向图的有向边换成无向边得到的图是连通图&#xff0c…

如何在 Ubuntu 上安装和配置 Tomcat 服务器?

简介&#xff1a;最近有粉丝朋友在问如何在 Ubuntu 上安装和配置 Tomcat 服务器&#xff1f;今天特地写这篇文章进行解答&#xff0c;希望能够帮助到大家。 文章目录 Ubuntu上安装和配置Tomcat的详细步骤Tomcat在Linux环境下的安装与配置一、下载并上传Tomcat压缩包二、启动To…

【单片机】CJSH22-CH2O,甲醛传感器,甲醛传感器数据读取处理

原理图 解析程序 逻辑是&#xff1a; 1、初始化串口和定时器10ms中断 2、循环读取一帧数据到rev_CH2O_bufferdata 3、在主函数解析数据rev_CH2O_bufferdata 4、最终的pm2.5数值就是CH2O_value 使用CH2O_value的数据即可。 PPB单位&#xff0c;除以1000就是ppm&#xff0c;再…