C++笔记

将数字以十六进制输出:cout<<hex<<100<<endl;

将数字以八进制输出:cout<<oct<<100<<endl;

精度控制

include

保存a位小数:setprecision(a)

将b保留a位:cout<<setprecision(a)<<b<<endl

将b保留小数点后a位:cout<<setiosflags(ios::fixed)<<setprecision(a)<<b

const限定符:限制局部变量为常量

ae+N:a*10n

ae-N:a*10-n

名称空间:控制名称作用域

程序中创建不同名称空间

  1. 声明区域:可以在区域中进行声明
  2. 潜在作用域:从变量声明点开始,到声明区域

使用空间名名称

  • 除了用户定义的名称空间,还有全局文件名称空间

  • 名称空间可嵌套使用,开放且可以随时添加新内容<如果同名做合并操作>

  • 名称空间可以匿名隐式加上static

  • 可以起别名:A=B

  • 匿名的名称空间可直接访问

构造函数:程序声明对象是否可自动调用

  • 数据成员名中使用m_前缀或成员名中使用后缀_

  • public:一个类的构造函数名和类名相同

  • 引用:&别名=原名 两个名称共享内存空间

  • 引用一旦初始化就无法更改,引用作函数传参:形参修饰实参

  • 简化实参:值、地址、引用

  • 本质是常量指针const

  • 如果函数声明有默认实参,那么函数定义则不用加(一个就行)

  • 现阶段函数占位意义不大

函数重载细节

  1. 引用作为条件
  2. 碰到默认参数(报错)

类中属性、行为统一叫成员

成员属性、成员变量、成员方法

权限 类内 类外 继承性
public(公共权限) 可访问 可访问 可继承
protected(保护权限) 可访问 不可访问 可继承
private(私有权限) 可访问 不可访问 不可继承

类外想要访问私有/保护权限对象,只能通过公共权限提供接口

class默认权限私有

struct默认权限公共

初始化列表方式

  • fun(int a,int b):A(a),B(b)

  • 类对象作为类成员

  • 隐式转换法

  • 类内static:共享内存

静态成员对象两种访问方式

  • 通过对象访问 对象.成员

  • 通过类名访问 类名::成员

  • 静态成员变量有访问权限

  • 直接在类里面定义的变量为私有变量

构造函数:类名(){}

无返回值且无void

与类名相同

可以有参数且发生重载

  • 调用对象时自动调用构造

析构函数:~类名(){}

  • 创建类时调用构造函数,类注销时调用析构函数
  • 拷贝构造函数,默认构造调用不用加括号
  • 浅拷贝:拷贝指针
  • 深拷贝:拷贝数据
  • 静态成员函数(有访问权限的),所有对象共享同一个函数(内存空间),只能访问静态成员变量
  • 不可以访问非静态成员变量

对象模型和this指针:成员变量和成员函数分开存储

  • 空对象占用内存空间1B,为了区分空对象位置

  • 每个空对象有独一无二地址

  • this指针是隐含每一个非静态城公园函数内的指针

用途:

  • 解决名称冲突

  • 返回对象自身

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

  • this指向p2的指针,*this指向p2本体

常函数:

  • 成员函数后加const

  • 不可修改成员属性

  • 加关键字mutable,常函数依然可修改

  • 成员后加congst,修饰this指向

类内声明:friend void fun(c)

  • 这样fun可访问c的私有成员,不用特地使用public声明

  • 类外创建类内成员函数

  • 类名::成员函数(){}

运算符重载

type operator+(type &A){}

  • 成员函数重载(可链式嵌套)

  • 全局函数重载

type operator+(type &A1,type &A2){}

  • 给运算符新的定义,赋予其另一种功能

  • 适应不同数据类型

  • 对于内置数据类型不可重载

  • 不要滥用运算符重载

左移运算符重载<<

  • operator<<()

  • 全局函数重载左移运算符(只能在全局中)

  • ostream operator<<(ostream &cout,type &A){}

递增运算符重载++

  • operator++()前置重载

  • operator++(int)后置重载

  • 记录结果

  • 后递增

  • 返回

  • 总之,重载一定会用到operator

赋值运算符重载

关系运算符重载

函数调用符重载()

  • 仿函数:重载起来像函数被调用

  • 继承:下级别成员拥有上级别的共性

减少代码重复

class A:public B{}

  • A继承B中所有内容

class 子类:继承方式 父类{}

public、protected、private

  • A:元素+方法(多种)

  • B:元素+方法(单种)

继承中对象模型

  • 父类中所有非静态成员都会被子类继承

  • 继承构造和析构顺序

  • 先构造父类,后子类

  • 先析构子类,后父类

  • 继承同名成员处理方式

  • 通过子类对象访问继承成员,应加作用域 父类::子成员

  • 直接调用的是子类成员

  • 子类成员会隐藏父类中继承下来的方式

  • 同名静态成员继承:对象.类名访问

  • 多继承:class子类:方式 父类1,方式 父类2

菱形继承:二义性处理

虚继承(继承指针)

  • 多态:静态多态:函数/运算符重载

  • 动态多态:派生类和函数运行时多态

满足条件:

继承关系

子类重写父类虚函数

重写:函数返回值类型、函数名、参数列表相同

动态多态使用:子类重写父类虚函数

父类引用接受子类对象可行,允许父子类型转换。而要让父类使用子类的方法,则将父类定义为虚函数就行。

引用时晚绑定则可避免引用时父类指向子类问题。

引用类型取决于等号右边

原理剖析

vfptr:virtual function pointer

  • 虚函数指针表

vftable:虚函数表(记录虚函数地址)

  • 当子类重写父类虚函数,子类虚函数表内部会替换为子类虚函数地址

  • 当父类指针或引用指向子类对象,发生多态

开闭原则:扩展开放,修改关闭

  • 计算器基类:抽象

  • 高内聚,低耦合

纯虚函数:

  • 父类中虚函数无实际意义

  • 重点在于子类中重写的功能

  • 当类中有了纯虚函数,这个类也称抽象类

  • 抽象类无法实例化对象,因此抽象子类必须重写父类,否则无法实例化对象

  • 虚函数代码毫无意义,作用在于子类重写

  • 用父类指针接收不同的子类

  • 而多态给函数提供扩展性(传入指针)

虚析构/纯虚析构

  • 父类对象无法析构子类对象,从而导致内存泄漏。虚析构解决此类问题

  • virtual ~fun()=0

  • 纯虚析构函数应当有具体实现

  • 而调用子类时使用指针

文件操作

  • ofstream:写操作

  • ifstream:读操作

  • fstream:读写

创建流对象:

  • ofstream ofs;

  • ofs.open()

  • ofs<<数据;

  • ofs.close()

打开方式:

  • ios::

  • in读

  • out写

  • ate文件尾

  • app追加

  • trunc删除创建

  • binary二进制

读写步骤相似

  • ifs.getline()行读

  • ifs.get()一个个读

模板

泛型编程

函数模板\类模板

template

声明一个模板,以至于后面不报错

类型不同,其它一样,则可用模板

template

  • 自动类型推导,显示指定类型

  • 函数模板注意事项

  • 自动类型推导,必须推导出一致数据类型T才可使用

  • 模板必须确定T数据类型才能使用

typename/类模板

  • 显式指定类型发生隐式类型转换

  • 普通函数和函数模板调用规则

  • 如果函数模板和普通函数都可调,优先使用普通函数

  • 可使用空模板参数列表强制使用函数模板

  • 函数模板可发生重载

  • 如果函数模板可产生更好匹配,优先调用函数模板

  • 如果函数模板产生更好匹配,优先调用函数模板

局限性

  • 并非万能,特殊数据类型需要特殊自定义数据类型实现具体化代码,优先调用具体化

  • template<>fun(typename &A)

  • 故不用运算符重载也能实现

类模板

  • template<class A,class B>

  • 无自动类型推导功能,可以有默认参数

  • 类模板可以有默认参数

  • 类模板对象作函数参数

typeid(A).name()

类模板与继承

子类继承的父类式一个类模板

需要指定父类中T的类型,如果不指定,编译器无法给子类分配内存

如果想灵活指定父类中T类型,子类也需要变类模板

如果父类是类模板,子类需要指定出父类中T的数据类型

类模板成员函数类外实现

template<class T1,class T2>

class P{}

template <class T1,class T2>

P<T1,T2>:😛(T1 A,T2 B){}

成员函数类外实现

类模板分文件编写

将声明和实现包含到一个文件

.hpp

.h声明

.cpp 实现

类模板与友元

类内:直接类内声明友元即可

类外:提前让编译器知道全局函数存在

编程技巧:

创建头文件.h

功能在.h中进行声明

具体实现在cpp中进行

父类指针承接子类对象

STL模板库(standard template libary)

泛型编程->提升代码通用性

建立一套数据结构和算法标准

  • 容器
    • 序列式:每个元素都有固定位置
    • 关联式:没有严格顺序关系
  • 算法
    • 质变:更改元素内容
    • 非质变:不会更改元素内容
  • 迭代器
    • 算法通过迭代器访问容器
    • 输入、输出、双向、前向、随机访问
  • 仿函数
  • 适配器
  • 空间配置器

容器

  • vector 存放自定义数据类型

  • vector

容器可存储地址

  • vector

容器中嵌套容器

  • vector

  • 二维数组实现方式

string容器

赋值操作

  • string& operator=(const char* s)

    • 将char*赋值给当前字符串
  • string& operator=(const string& s)

    • 把字符串s赋值给当前字符串
  • string& operator=(char c)

    • 把字符串赋给当前字符串
  • string& assign(const char *s)

    • 把字符串s赋给当前字符串
  • string& assign(const char* s,int n)

    • 把字符串s前几个字符赋给当前字符串
  • string& assign(const string& s)

    • 用n个字符c赋给当前字符串
  • string& assign(int n,char c)

    • 字符串拼接
  • append(const char* s,int n)

    • 将s前n个字符连接到当前字符串结尾
  • append(const string& s,int pos,int n)

    • 将s从第pos开始几个字符连到字符串结尾

string查找

  • find(string,pos)

    • 查找str第一次出现位置
  • find(s,pos)

    • 查找s出现的位置
  • find(char,pos)

    • 查找char第一次出现位置
  • refind()

    • 从最后开始查找
  • replace()

替换

  • string比较:按ASCII码对比:=返回0

  • compare():<返回-1

[]返回单个字符

at()

string插入和删除

  • insert()

  • erase()

string截取

  • .substr(int a,int b)

  • 从第a+1个开始取长度为b

vector可以动态扩展

front() back() push_back()

vector容器

  • vector v1(v.begin(),v.end())

  • vector v2(a,b) a个b传入v2

  • vector v3(v) 拷贝构造函数

赋值

  • =
  • assign(begin)\assign(end)
  • assign(a,b)

容量大小

  • empty() 判断是否为空

  • capacity() 容器容量

  • size() 容器中元素个数

  • resize() 重新指定容器长度,长则填充短则删除

vector删除、插入

  • pushback()

  • pop_back()

  • insert(pos,element)

  • erase(pos)

  • clear()

数据存取

  • at().[].front().back()

容器互换

  • swap收缩内存

  • v1和v互换

  • v1.swap(v)

预留空间

  • reserve(len)

减少vector动态

  • 预留len大小空间,位置不初始化,元素不可访问,避免存储过程中不断开辟新空间

deque容器

双端数组

与vector区别

  • vector对头部插入删除效率低,数据量越大,效率越低
  • deque相对而言,对头部插入删除比vector快
  • vector访问元素速度比deque快

内部有中控器,维护每段缓冲区地址,支持随机访问

  • deque构造和vector相似:赋值\大小\插入\删除\数据与vector相同

  • deque排序

  • sort(d.begin(),d.end())

默认升序

  • 对于支持随机访问的迭代器容器

  • 都可用sort算法直接排序

stack容器

list容器

  • 链表(双向循环链表)
  • 结点:数据\指针
  • 迭代器只支持前移后移

赋值交换

  • assign()
  • swap()

大小操作

  • size()
  • empty()
  • resize()
  • reverse()
  • sort()

set\nultiset容器

  • 关联式容器,底层为二叉树
  • set容器不允许插入重复值,且自动排序
  • multiset允许插入重复值

接口

  • size()
  • empty()
  • swap()
  • insert()
  • clear()
  • erase()
  • find()
  • count()

pair容器

pair p(value)

set排序规则

指定自定义排序规则

仿函数 operator() 函数重载

map\multimap全为pair

字典 key:value

map 不允许重复key值,而multimap允许insert(pair)

map容器

  • 函数对象重载()时叫仿函数,本质是类可像普通函数那样调用
  • 函数对象可以有自己的状态(成员变量)

谓词

  • 返回bool类型仿函数
  • 如果operator()接受一个参数,那么叫一元谓词
  • 内建函数对象:算数\关系\内建

include

一元仿函数,nagate<>取反

关系仿函数\逻辑仿函数

常用仿函数

常用算法:

常用遍历算法

for_each(v.begin(),v.end(),func())

transform 搬运容器到另一个容器

查找:查找指定元素,返回指定迭代器

  • find:查找元素
  • find_if:按条件查找元素
  • adjacent_find:查找相邻重复元素
  • binary_search:二分查找法
  • count:统计元素个数
  • countif:按条件统计元素个数

常用排序算法

  • sort:对容器元素排序
  • randomshuffle:打乱元素次序
  • merge:容器元素合并
  • reverse:反转指定范围元素

拷贝:替换算法

  • copy:容器内指定范围元素拷贝到另一容器
  • replace:指定范围内调元素改为新元素
  • replace_if:指定范围满足条件元素替换为新元素
  • 互换两容器元素

算术生成算法

  • accumulate:计算容器累计元素总和
  • fill:向容器添加元素

集合算法

  • set_intersection:求容器交集
  • set_union:求并集
  • set_difference:求差集
posted on 2023-08-23 20:50  读研随想录  阅读(13)  评论(0编辑  收藏  举报