c++ 学习

Day 01

命名空间

  • 三种方式
using std::cout;//全部文件使用的cout来自std

std::cout << "hello" << std::endl;//用的地方指定

using namespace std;//把std所有的命名空间全部引入
  • 定义一个命名空间
    在这里插入图片描述
  • 07 using声明和using编译指令
    在这里插入图片描述

对C语言增强的地方

  • 在c++中,变量可以随用,随定义;C一般要求定义在前面;
  • c中对全局变量重复定义,会解释为一个是声明;c++会报错
    在这里插入图片描述
  • struct student在c中定义变量要加上struct;在c++中不用(把他当成类处理)直接student s1
    在这里插入图片描述
  • 对于函数在c中不写返回值(默认是int),不会报错;c++强制要写
  • 在c中可以传多余的参数
  • 增加了bool类型
  • 三目运算符在c++中可以当左值:返回的值变量的引用
    在这里插入图片描述
  • const的增强:针对直接赋值(通过指针,全局变量都不能改,局部变量c可以改,c++改的是临时变量的值,本身没有改)
    • 对const修饰的变量取地址的时候,会分配临时内存(一般来说分配了内存就可以通过指针改,但是这个临时的内存改了没有意义)

    • const前加入关键字external后也会分配内存,(这里通过指针改会报错)

    • 使用变量初始化const的变量可以通过指针修改在这里插入图片描述

    • 自定义的数据类型也可以通过指针修改 在这里插入图片描述

    • c中的const可以改(针对直接赋值)
      在这里插入图片描述

    • 在这里插入图片描述

    • 编译器看到a就会到文字常量区的符号表找到key值为a的value替代,类似于宏定义,不同的是宏定义是在预处理阶段,const处理是在编译阶段

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

    • 枚举的增强:c中可以用int表示(含义不清)

引用的基本语法

  • int &是引用的数据类型,就是别名;
    在这里插入图片描述

  • 通过引用,在函数传参的时候可以用引用做形参接收,回避了传指针的麻烦;
    在这里插入图片描述

  • 引用的本质:int *const p(常指针,内容可变,p值不变)

  • 引用一定要定义的时候初始化,跟const一样

  • 引用的大小和指针一样

  • int *const p=&a
    在这里插入图片描述
    在这里插入图片描述

  • 有关常指针:数组为例
    在这里插入图片描述

  • 引用作为函数的返回值:

  • 引用作为返回值,不要返回局部变量的引用

  • 如果是在堆上开辟的,或者是static定义的局部变量可以返回

  • 函数可以作为左值(如果函数返回值是指针,他也是返回的是数值,不能作为左值,但是引用可以)

  • 在这里插入图片描述

  • 指针引用

    • 避免了二级指针操作中容易出错
      在这里插入图片描述
  • const 修饰引用(可以通过指针修改)
    在这里插入图片描述

    • 引用用在形参上(可以不用开辟新的空间),但是为了防止误操作改变外面的量,可以加上const:
      在这里插入图片描述

内联函数

  • 如果反复多次调用一个函数,就会有多次进出栈的操作,为了避免这个开销。引入内联函数
  • 内联函数的作用类似于宏函数(但是宏函数不会检查语法错误。,是在预处理阶段做的,没有语法检查的能力)
  • 内联函数是编译阶段做的,有语法的检查能力,本质就是在调用处,原处展开。(但是不会无限展开,如果代码量太大,为了避免过于占用内存,还是会进出栈操作,比如在inline里加个1000次的循环),一般用在一两行代码,要反复运行的位置(牺牲空间换时间)
  • 成员函数一般都很短,他们都隐藏了关键字inline
    在这里插入图片描述

进入18

函数的默认参数以及占位参数

  • 带默认参数
    在这里插入图片描述
  • 函数的声明和实现只能有一个有默认参数
  • 函数的占位参数:符号重载用
    在这里插入图片描述
  • 函数重载(不是复写)
    在这里插入图片描述

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

  • 原理:编译器针对不同的函数,修改了函数名

externC

  • 因为c++独有的函数重载机制,编译器会修改函数名(方便找到函数),所以在c++编译器上运行c++代码要加上一下带条件宏定义:
    在这里插入图片描述

c语言的结构体不做类型的检测,完全只是内存大小相同即可,只是检测指针的步长。导致不同的结构体,只要内存分配相同,可以同样传递:

  • 例如一个函数要求传入的结构他为person但是另一个结构体dog内存分配与人相同也可以传入该函数。
  • c语言中结构体里只能放属性,不能放行为(函数,要函数指针才行)

c++中struct和class区别就是默认权限不同,struct默认public,class默认private(class相比struct增加了权限控制)

Day02

类相关

构造函数和析构函数

  • 编译器自动调用

  • 编译器自动生成空的无参构造和析构

  • 在公共作用域下

  • 构造:没有返回值,也不用写void,跟类名写法一样,可以重载

  • 析构:函数名前加~

  • 拷贝构造函数(就是拷贝一个对象):传的是同类对象的引用,防止修改要加const

    • 要用&接收,不用的话就是值传递。要新创建对象,就进入了无限的循环
      在这里插入图片描述
  • 调用:

    • 括号法:
      在这里插入图片描述
    • 显示法:
      在这里插入图片描述
    • 注意点:
      在这里插入图片描述
    • 隐式法:
      在这里插入图片描述
  • 拷贝构造函数的调用时机

    • 当传值的时候,形参就是调用 了拷贝构造函数:Person p=p1(隐式法)
      在这里插入图片描述
    • 以值的方式返回局部对象
      在这里插入图片描述
  • 构造函数的调用规则
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

深拷贝与浅拷贝

  • 浅拷贝的时候只拷贝了指针,这样在释放的时候,其他有拷贝构造函数创建出来的对象p2先释放了指针,而本对象p1再释放就会崩溃;解决方法就是深拷贝:

在这里插入图片描述

  • 重写系统默认的拷贝构造函数(系统只会简单的值拷贝):
    在这里插入图片描述

初始化列表

  • 用来初始化属性
    在这里插入图片描述
    在这里插入图片描述
  • explicit关键字使用
    在这里插入图片描述
  • new和delete运算符:完成了开辟空间,调用构造函数(赋值),判断的复合工作
    • new
      在这里插入图片描述
      在这里插入图片描述
      区别
      在这里插入图片描述
    • 注意事项:
      在这里插入图片描述
    • 利用new创建数组
      在这里插入图片描述

静态成员

  • 为什么要在类外初始化:

    • 因为如果没有创建对象,类里面的代码不会运行;
    • 编译期(分配了空间)
    • 这个时候如果用类名访问就会报错(没有值)
    • 但是私有的静态成员,可以不用赋值,类外通过类名也访问不到,但是可以在类外赋值
  • 在这里插入图片描述

  • 访问方式
    在这里插入图片描述

  • 单例模式:

    • 私有有参构造和拷贝构造
    • 加了作用域:可以视为是在类内部执行的,所以能访问私有构造; 在这里插入图片描述

C++对象模型初探-成员变量和成员函数分开存储

  • 在这里插入图片描述

this指向被调用成员函数所属的对象

  • 编译器编译的时候,把this指针已经加入了:
    在这里插入图片描述
    在这里插入图片描述- 空指针访问成员函数
    • 也可以访问没用用到this 的成员函数;否则会崩溃

常函数和常对象

在这里插入图片描述

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

  • 加上关键字mutable
    在这里插入图片描述
  • 常对象
    在这里插入图片描述
    • 常对象不能调用普通的成员函数,只能调用常函数。

友元

  • 全局函数作为友元函数

    • 在类中用friend关键字+全局函数的声明,就能访问该类内部的私有属性
      在这里插入图片描述
  • 友元类

    • 友元类不一定有传递性,可逆性
    • 类内的函数,可以放在类外部实现,加上命名空间就行
      在这里插入图片描述
      同样:在这里插入图片描述
  • 同理也可以是指成员函数,作为另一个类的友元;

数组类封装

运算符重载

  • 加运算符:分别利用成员函数,和全局函数

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

  • 左移运算符重载

    • 要用全局函数实现
      在这里插入图片描述
    • 返回引用是为了链式编程 在这里插入图片描述
  • 递增运算符重载++

  • 前置++:一般放在成员函数,考虑到一直要操作,所以要返回引用,例如:++(++a)
    -在这里插入图片描述 - 后置++:返回的是临时变量,本体内部已经记录了;临时变量方法调用完会回收,所以不能返回引用;
    在这里插入图片描述

  • 由于后置++产生了临时副本,所以为了效率考虑,推荐日常使用前置++;
    在这里插入图片描述

  • 指针运算符重载-智能指针
    在这里插入图片描述

  • 赋值运算符重载
    在这里插入图片描述

  • []运算符重载

  • 关系运算符重载

  • 函数调用运算符重载

  • 不要重载逻辑与和逻辑或符号:因为没法实现短路的效果
    在这里插入图片描述

Day03

继承和派生

  • 语法:class 子类:继承方式:父类
  • 继承方式
    在这里插入图片描述
    • protected 子类可以访问,其他地方不可访问
    • private 只有自己类可以访问

继承中的对象模型

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

继承中的构造和析构

  • 在这里插入图片描述

  • 子类默认走父类的无参构造,但是可以利用初始化列表指定要走的父类构造函数(类似于java中的super):
    在这里插入图片描述

  • 子类不继承父类的构造函数和析构函数,只有父类才知道怎么样构造和析构自己的属性

  • 继承中的同名成员处理

  • 在这里插入图片描述

  • 继承中的同名静态成员处理
    在这里插入图片描述
    在这里插入图片描述

  • 多继承的语法
    在这里插入图片描述

  • 菱形继承问题以及解决

  • 使用虚继承处理两份数据的问题(二义性,浪费内存)
    在这里插入图片描述
    在这里插入图片描述

  • 虚继承的内部工作原理剖析

    • 一旦使用了虚继承,那么内部之前绑定的变量就会变成指针,指向一个表,表中的内容就会根据子类是否重写而覆盖

多态相关

-动态联编,通过虚函数实现-
在这里插入图片描述
在这里插入图片描述

  • 多态原理
    在这里插入图片描述
  • 多态的好处(计算器案例)
    • 把要干什么和怎么干分开
    • 在这里插入图片描述
  • 纯虚函数的类,也叫抽象类
    • 纯虚函数子类一定要重写
    • 纯虚函数跟java的抽象函数类似;
    • 在这里插入图片描述
  • 虚析构和纯虚析构
  • 虚析构:当子类有的属性是创建在堆区上的,那么就要重写析构函数,为了子类delete的时候能够调用到,父类的析构函数应该写成虚析构;
  • 纯虚析构和纯虚函数不同:由于父类的析构函数一定会被调用(父类自己也有属性可能在堆区,自己也要释放),所以要有函数体;但是纯虚函数已经=0,所以函数体写在外面;
    在这里插入图片描述
  • 纯虚析构 有了之后,也变成了抽象类;
    在这里插入图片描述
  • 向上向下类型转换
    在这里插入图片描述
    在这里插入图片描述
  • 重写、重载、重定义;
    • 重定义: 在这里插入图片描述在这里插入图片描述

泛型编程

模板技术

在这里插入图片描述

  • 引用传递的时候原名的类型和别名的类型一定要一致,编译器不会自己帮你转(例如char 转 int),但是普通的传递会转
    在这里插入图片描述
  • 模板使用:编译器推导出来了也行;推不出来就要指定(比如:函数都没有参数的时候)

在这里插入图片描述

  • 函数模板和普通函数的区别以及调用规则
    • 区别:
      在这里插入图片描述
      -规则:
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
  • 模板机制
    在这里插入图片描述
    • 函数模板通过传入的T的类型生成了模板函数(编译器内部生成的)
      在这里插入图片描述
    • 模板的局限性以及解决:不能真的针对每一个类型
      在这里插入图片描述
      在这里插入图片描述
类模板
  • 与函数模板的区别:

    • 类模板不能使用自动类型推导,必须显示指定
    • 类模板中的类型可以有默认参数(默认什么类),函数模板不行;
  • 泛型编程:体现在模板技术;特点是将类型参数化;

  • 类模板中的成员函数创建时机

    • 类模板的成员函数,并不是一开始就创建出来的,而是在运行阶段,传入了T的具体类型才创建出来的;
  • 类模板作为函数参数 在这里插入图片描述在这里插入图片描述在这里插入图片描述
    在这里插入图片描述

  • 类模板碰到继承的问题以及解决

    • 子类创建的时候必须要知道父类模板T是什么类型,否则无法给父类分配内存(因为要走子类父类的构造)
    • 如果子类是具体类(不是类模板),那就指定父类T的类型
      在这里插入图片描述
    • 如果子类是类模板,那么把自己的一个泛型交给父类就行:
      在这里插入图片描述
  • 类模板的类外实现
    在这里插入图片描述

  • 类模板的分文件编写问题以及解决
    在这里插入图片描述

  • 类模板碰到友元函数
    在这里插入图片描述

    在这里插入图片描述

  • 类模板案例—数组类封装

    • 需要注意的是,自定义对象的数组初始化前,会先初始化自定义对象(走无参的默认构造0),自定义类里的有参构造会默认删掉无参构造(所以自己手动补上)
      在这里插入图片描述

类型转换-静态类型和动态类型转换

在这里插入图片描述
- 自定义类型 支持继承类对象的,指针,引用间的转换;
- 没有继承关系的不支持

  • 动态转换(严谨)

    • 不安全或者丢失精度都不让转
      在这里插入图片描述
  • 类型转换-常量类型

    • 不允许把非指针或者非引用做const_cast转换(不能把常量转成变量)
      在这里插入图片描述
  • 重新解释类型转换(不安全,不建议用)
    在这里插入图片描述
    在这里插入图片描述

Day04

  • 异常的基本语法

    • 为什么要有异常:c中的返回值判断有缺陷(可能是异常,也可能是正常值) 在这里插入图片描述
      在这里插入图片描述
  • 抛出自定义异常:跟java不一样,不用继承exception的父类

  • 栈解旋 在这里插入图片描述

  • 异常的接口声明 在这里插入图片描述
    在这里插入图片描述

  • 异常变量的生命周期

    • 值的方式接受对象,会调用拷贝构造
      在这里插入图片描述
    • 用引用接受
      在这里插入图片描述
  • 用指针接收,匿名对象走完本行没有变量接收就会回收,指针就变成野指针(接收匿名对象的地址没有用)
    在这里插入图片描述

  • 异常变量如果抛出有接收的话,在抛出的函数体内创建的对象不会释放(即使是创建在栈上,创建在堆上的更不会),他的生命周期跑到了catch的函数体里;不像函数返回值(会在本函数结束的时候释放栈里的内容),理解:一个抛字,抛出去了就不规我管了。
    在这里插入图片描述

  • 异常的多态使用

    • 继承基类异常,由基类异常的引用接受
      在这里插入图片描述
  • 使用C++系统标准异常类

  • 编写自己的异常类(继承系统的)

    • char* 不可以直接赋值给string,要通过构造函数string(char*)
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
  • 标准输入流
    在这里插入图片描述

  • 理解:cin就是键盘的缓冲区(输入的数据现在缓冲区,cin.get就是在这个缓冲区拿);同理cout也有缓冲区,endl会刷新缓冲区,并加上\n换行符;

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

  • 标准输出流

  • 格式化输出(成员函数法)
    在这里插入图片描述

    • 控制符法:
      在这里插入图片描述
  • 文件的读写

    • 写:
      在这里插入图片描述

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

STL(标准模板库)

STL概述和六大组件

  • STL包含container,algorithm,iterator,仿函数,适配器,空间配置器
  • 都是理论:
    在这里插入图片描述
  • 容器算法迭代器初识
  • 就是模板声明:类似java中的集合,列表

在这里插入图片描述
-遍历的三种方式:第三种用到里系统的算法要引入algorithm库 在这里插入图片描述

string容器

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

  • 隐式类型转换
    在这里插入图片描述
    在这里插入图片描述

vector容器(动态开辟)

在这里插入图片描述

  • 动态空间并不是直接在后面,而是重新开辟一个,把数据复制过去,原有的空间数据失效;所以vector的capacity≥size;
  • resize后vector的capacity过大,缩小的方法
    在这里插入图片描述
  • 用reverse预留空间:避免往vector中不停插入数据的同时,系统繁复的开辟空间,复制数据,释放空间:v.reverse(100000)
    在这里插入图片描述
  • 逆序遍历
    在这里插入图片描述
  • 判断容器是否支持随机访问
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

deque:两端,方便头部插入/删除;而vector是单端的,要在头部插入,先需要把本身的数据后移;

在这里插入图片描述

  • 原理:分段连续空间
    在这里插入图片描述
  • 迭代器总结:
    在这里插入图片描述
    -

Day 05

stack栈容器

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

  • queue队列容器:只能访问到队头和队尾,中间的部分访问不到,所以依然不能遍历(没有迭代器);
    在这里插入图片描述

  • list容器(物理不连续–双向循环链表)
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  • set容器(自动排序),序列式容器

    • key和value同为一个
  • multiset允许有重复值
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  • 对组的声明方式
    在这里插入图片描述

  • 判断是否插入成功,返回值也是对组pair(set);但是mutilset不反回对组
    在这里插入图片描述

  • 对于是不能修改里面的元素,所以不能修改排序规则,但是在插入元素之前,可以指定好set的排序规则;

  • 仿函数类似于python中的闭包:

  • https://www.cnblogs.com/decade-dnbc66/p/5347088.html
    在这里插入图片描述

  • map容器
    在这里插入图片描述

  • 插入方式:
    在这里插入图片描述
    在这里插入图片描述

  • STL容器使用时机
    在这里插入图片描述

  • 函数对象(仿函数):本质是一个类
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  • 谓词

    • 有几个参数就是几元
    • 谓词指的是返回值是bool值
    • lambda表达式
      在这里插入图片描述
      在这里插入图片描述
  • 内建函数对象 引入functional头文件
    在这里插入图片描述

适配器(难)

- 函授对象适配器
![在这里插入图片描述](https://img-blog.csdnimg.cn/20181031210915439.png)![在这里插入图片描述](https://img-blog.csdnimg.cn/2018103121054477.png)

在这里插入图片描述

  • 取反适配器
    在这里插入图片描述

  • 函数指针适配器(上面都是针对函数对象的,这是针对函数的)
    - 将函数指针适配成函数对象
    在这里插入图片描述

  • 成员函数适配器
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

常用遍历算法

  • 遍历:传函数,或传仿函数
  • for_each有返回值
    在这里插入图片描述
  • transform 容器转移
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

常用查找算法

  • find(针对对象):找自定义类型,要在自定义类型里面重载==操作符
    在这里插入图片描述

  • find_if(针对指针):自己定义条件:可以用适配器,和仿函数
    在这里插入图片描述

  • adjacent_find
    在这里插入图片描述

  • binary_search:需要有序序列才能用

  • count

  • count_if(按条件统计,回调或者仿函数的返回值是bool)

常用排序算法

  • merge:把两个有序的合并
    在这里插入图片描述

  • sort:
    在这里插入图片描述

  • random_shuffle:随机打乱

  • reverse
    在这里插入图片描述

常用的拷贝和替换算法

在这里插入图片描述

  • copy
  • replace
  • replace_if
  • swap
    在这里插入图片描述

常用算数生成算法

  • accumulate
    在这里插入图片描述
  • fill
    在这里插入图片描述
    在这里插入图片描述

常用集合算法

  • set_intersection
    在这里插入图片描述

  • set_union

  • set_difference:A与B的差集,和B与A的差集不一样