栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C++ Primer知识框架随笔(基础部分)

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C++ Primer知识框架随笔(基础部分)

c++基础
  • 1 开始
    • 1.1 编写一个简单的c++程序
      • 1.1.1 编译、运行程序
        • 程序源文件命名约定
        • 从命令行运行编译器
    • 1.2 初识输入输出
        • 标准输入输出对象
        • 一个使用IO库的程序
        • 向流写入数据
        • 使用标准库中的名字
        • 从流读取数据
        • 完成程序
    • 1.3 注释简介
        • C++中注释的种类
        • 注释界定符不能嵌套
    • 1.4 控制流
      • 1.4.1 while语句
      • 1.4.2 for语句
      • 1.4.3 读取数量不定的输入数据语句
      • 1.4.4 if语句
    • 1.5 类简介
      • 1.5.1Sales_item类
      • 1.5.2 读写Sales_item
      • 1.5.3 Sales_item对象的加法
      • 1.5.6 初识成员函数
    • 1.6 书店程序
  • 2 变量和基本类型
    • 2.1基本内置类型
      • 2.1.1 算术类型
        • 带符号类型和无符号类型
      • 2.1.2 类型转换
        • 含有无符号类型的表达式
      • 2.1.3 字面值常量
        • 整型和浮点型字面值
        • 字符和字符串字面值
        • 转义序列
        • 指定字面值的类型
        • 布尔字面值和指针字面值
    • 2.2 变量
      • 2.2.1 变量定义
        • 初始值
        • 列表初始化
        • 默认初始化
      • 2.2.2 变量声明和定义的关系
      • 2.2.3 标识符
        • 变量命名规范
      • 2.2.4 名字的作用域
        • 嵌套的作用域
    • 2.3 复合类型
      • 2.3.1 引用
        • 引用即别名
        • 引用的定义
      • 2.3.2 指针
        • 获取对象的地址
        • 指针值
        • 利用指针访问对象
        • 空指针
        • 赋值和指针
        • 其他指针操作
        • void*指针
      • 2.3.3 理解复合类型的声明
        • 定义多个变量
        • 指向指针的指针
        • 指向指针的引用
    • 2.4 const限定符
        • 初始化和const
        • 默认状态下,const对象仅在文件内有效
      • 2.4.1 const的引用
        • 初始化和对const的引用
        • 对const的引用可能会引用一个并非const的对象
      • 2.4.2 指针和const
        • const指针
      • 2.4.3 顶层const
      • 2.4.4 constexpr和常量表达式
        • constexpr变量
        • 字面值类型
        • 指针和constexpr
    • 2.5 处理类型
      • 2.5.1 类型别名
        • 指针、常量和类型别名
      • 2.5.2 auto类型说明符
        • 复合类型、常量和auto
      • 2.5.3 decltype类型指示符
        • decltype和引用
    • 2.6 自定义数据结构
      • 2.6.1 定义Sales_data类型
        • 类数据成员
      • 2.6.2 使用Sales_data类
        • 添加两个Sales_data对象
        • Sales_data对象读入数据
        • 输出两个Sales_data对象的和
      • 2.6.3 编写自己的头文件
        • 预处理器概述
  • 3 字符串、向量和数组
    • 3.1 命名空间的using声明
      • 每个名字都需要独立的using声明
      • 头文件不应包含using声明
      • 一点注意事项
    • 3.2 标准库类型string
      • 3.2.1 定义和初始化string对象
        • 直接初始化和拷贝初始化
      • 3.2.2 string对象上的操作
        • 读写string对象
        • 读取未知数量的string对象
        • 使用getline读取一整行;
        • string的empty和size操作
        • string::size_type类型
        • 比较string对象
        • 为string对象赋值
        • 两个string对象相加
        • 字面值和string对象相加
      • 3.2.3 处理string对象中的字符
        • 使用基于范围for语句处理每个字符
        • 使用范围for改变字符串中的字符
        • 只处理一部分字符?
        • 使用下标执行迭代
        • 使用下标执行随机访问
    • 3.3 标准库类型vector
      • 3.3.1 定义和初始化vector对象
        • 列表初始化vector对象
        • 创建指定数量的元素
        • 值初始化
        • 列表初始值还是元素数量?
      • 3.3.2 向vector对象中添加元素
        • 向vector对象添加元素蕴含的编程假定
      • 3.3.3 其他vector操作
        • 计算vector内对象的索引
        • 不能用下标形式添加元素
    • 3.4 迭代器介绍
      • 3.4.1 使用迭代器
        • 迭代器运算符
        • 将迭代器从一个元素移动到另外一个元素
        • 迭代器类型
        • begin和end运算符
        • 结合解引用和成员访问操作
        • 某些对vector对象的操作会使迭代器失效
      • 3.4.2 迭代器运算
        • 迭代器的算术运算
        • 使用迭代器运算
    • 3.5 数组
      • 3.5.1 定义和初始化内置数组
        • 显示初始化数组元素
        • 字符数组的特殊性
        • 不允许拷贝和赋值
        • 理解复杂的数组声明
      • 3.5.2 访问数组元素
        • 检查下标的值
      • 3.5.3 指针和数组
        • 指针也是迭代器
        • 标准库函数begin和end
        • 指针运算
        • 解引用和指针运算的交互
        • 小标和指针
      • 3.5.4 C风格字符串
        • C标准库String函数
        • 比较字符串
        • 目标字符串的大小由调用者指定
      • 3.5.5 与旧代码的接口
        • 混用string对象与C风格字符串
        • 使用数组初始化vector对象
    • 3.6 多维数组
        • 多维数组的初始化
        • 多维数组的下标引用
        • 使用范围for语句处理多维数组
        • 指针和多维数组
        • 类型别名简化多维数组的指针
  • 4 表达式
  • 5 语句
  • 6 函数
    • 6.1 函数基础
        • 编写函数
        • 调用函数
        • 形参和实参
        • 函数的形参列表
        • 函数返回类型
      • 6.1.1局部对象
        • 自动对象
        • 局部静态对象
      • 6.1.2 函数声明
        • 在头文件中进行函数声明
      • 6.1.3 分离式编译
        • 编译和链接多个源文件
    • 6.2 参数传递
      • 6.2.1 传值参数
        • 指针形参
      • 6.2.2 传引用参数
        • 使用引用避免拷贝
        • 使用引用形参返回额外信息
      • 6.2.3 const形参和实参
        • 指针或引用形参与const
        • 尽量使用常量引用
      • 6.2.4 数组形参
        • 使用标记指定数组长度
        • 使用标准库规范
        • 显示传递一个表示数组大小的形参
        • 数组形参和const
        • 数组引用形参
        • 传递多维数组
      • 6.2.5 main:处理命令行选项
      • 6.2.6 含有可变形参的函数
        • 省略符形参
    • 6.3 返回类型和return语句
      • 6.3.1 无返回值函数
      • 6.3.2有返回值函数
        • 值是如何被返回的
        • 不要返回局部对象的引用或指针
        • 返回类类型的函数和调用运算符
        • 引用返回左值
        • 列表初始化返回值
        • 主函数main的返回值
        • 递归
      • 6.3.3 返回数组指针
        • 声明一个返回数组指针的函数
        • 使用尾置返回类型
        • 使用decltype
    • 6.4 函数重载
        • 定义重载函数
        • 判断2个形参的类型是否相异
        • 重载和const形参
        • const_cast和重载
        • 调用重载的函数
      • 6.4.1 重载与作用域
    • 6.5 特殊用途语言特性
      • 6.5.1 默认实参
        • 使用默认参数调用函数
        • 默认实参声明
        • 默认实参初始值
      • 6.5.2 内联函数和constexpr函数
        • 内联函数可避免函数调用的开销
        • constexpr函数
        • 把内联函数和constexpr函数放在头文件内
      • 6.5.3 调试帮助
        • assert预处理宏
        • NDEBUG预处理变量
    • 6.6 函数匹配
        • 确定候选函数和可行函数
        • 寻找最佳匹配
        • 含有多个形参的函数匹配
      • 6.6.1 实参类型转换
        • 需要类型提升和算术类型转换的匹配
        • 函数匹配和const实参
    • 6.7 函数指针
        • 使用函数指针
        • 重载函数的指针
        • 函数指针的形参
        • 返回指向函数的指针
        • 将auto和decltype用于函数指针类型
  • 7 类
    • 7.1 定义抽象数据类型
      • 7.1.1 设计Sales_data类
        • 使用改进的Sales_data类
      • 7.1.2 定义改进的Sales_data类
        • 定义成员函数
        • 引入this
        • 引入const成员函数
        • 类作用域和成员函数
        • 在类的外部定义成员函数
        • 定义一个返回this对象的函数
      • 7.1.3 定义类相关的非成员函数
        • 定义read和print函数
        • 定义add函数
      • 7.1.4 构造函数
        • 合成的默认构造函数
        • 某些类不能依赖于合成的默认构造函数
        • 定义Sales_data的构造函数
        • =default的含义
        • 构造函数初始值列表
        • 在类的外部定义构造函数
      • 7.1.5 拷贝、赋值和析构
        • 某些类不能依赖于合成的版本
    • 7.2 访问控制与封装
    • 7.3 类的其他特性
    • 7.4 类的作用域
    • 7.5 构造函数再探
    • 7.6 类的静态成员

1 开始 1.1 编写一个简单的c++程序
主要介绍了 main函数的组成
1.1.1 编译、运行程序
程序写完了要编译,编译完要运行程序
程序源文件命名约定
啥是源文件以及c++的文件后缀是啥,后缀的作用是啥
从命令行运行编译器
输入`编译器程序名字+程序文件名字`就是编译文件
输入“运行程序路径”就是在执行该文件“
1.2 初识输入输出
C和C++本身都没有为输入输出提供专门的语句结构。
输入输出并不是有C++本身定义的,而是在编译系统提供的I/O中定义的
介绍了iostream库包含2个基础类型分别表示输入流istream以及输出流ostream
库类型
标准输入输出对象
主要介绍了4个io对象:cout cin clog cerr
一个使用IO库的程序
通过一个输入数字,然后输出求和的简单程序介绍了输入输出流
如何使用iostream库
向流写入数据
<<输出运算符的作用以及返回结果是啥
endl操纵符的效果
缓冲区的介绍
使用标准库中的名字
介绍了前缀std::的作用
啥是作用域运算符
啥是命名空间
从流读取数据
输入运算符>>的作用
完成程序
无
1.3 注释简介 C++中注释的种类
介绍了2种注释方法分别是 单行注释// 与 界定符注释
界定符跨行时最好用的风格是每行以一个*开头
注释界定符不能嵌套
单行注释会忽略任何内容
界定符注释不能,所以不能嵌套
1.4 控制流
程序设计语言允许我们写出更复杂的执行路径
1.4.1 while语句
通过一个1到10这10个数之和的程序介绍了while语句是如何执行的
条件就是一个产生真或者假的结果的表达式、
什么是语句块(程序块)
案例程序中涉及了<= +=运算符、前缀递增运算符
1.4.2 for语句
for语句的组成部分:循环体、循环头
循环头的组成部分:初始化语句、循环条件、一个表达式
1.4.3 读取数量不定的输入数据语句
将标准输入对象作为循环条件:while(std::cin>>value) statement;
检测的是流的状态,流没有遇到错误,则为真;遇到文件结束符、无效输入时为假
win系统下的文件结束符是 CRTL+Z、Mac系统是CRTL+D
1.4.4 if语句
案例是统计输入中每个值连续出现多少次的程序介绍了if语句
案例涉及到了相等运算符==
==相等运算符与=赋值运算符不要混淆
1.5 类简介
内置类型:由语言定义的类型如int
介绍了类类型:像内置类型一样自然;
一个类定义了一个类型,以及相关联的一组操作;
头文件的后缀.h
1.5.1Sales_item类
类型名就是类名;
介绍了Sales_item类的内容
1.5.2 读写Sales_item
一个简单的输入输出
1.5.3 Sales_item对象的加法
反复从键盘敲入字符是乏味的
使用文件重定向:此机制允许我们将标准输入和标准输出与命名文件关联起来
执行文件名称 <输入文件> 输出文件名
1.5.6 初识成员函数
介绍了成员函数
点运算符.
调用运算符()
1.6 书店程序
本程序是对本章所学做的总结
2 变量和基本类型
介绍内置类型,并了解如何支持更复杂的数据类型
2.1基本内置类型
算术类型(字符、整型数、布尔值、浮点数)、空类型(void)
2.1.1 算术类型
算术类型的尺寸
带符号类型和无符号类型
无符号类型所有比特都用来存储值;
字符型被分为3种:char、unsigned char、signed char
2.1.2 类型转换
一些简单的类型转换例子;
赋值的过程会出现类型转换;
含有无符号类型的表达式
算术表达式中既有int又有unsigned时,int会转换为无符号数;
当无符号数减去一个值时,其结果不可能是一个负数;
2.1.3 字面值常量
字面值常量的形式和值决定了它的数据类型
整型和浮点型字面值
整型字面值可以写成10 8 16进制;
类型short没有对应的字面值;
10进制字面值不会是负数;
浮点型字面值默认是double;
字符和字符串字面值
单引号时字符;双引号是字符串;
转义序列
不可打印字符以及一些具有特殊含义的字符不能直接使用,需要转义字符;
最多跟3个数字组成转义序列;
X 跟着后面所有数字;
指定字面值的类型
使用一些前缀后缀可以改变整型、字符型、浮点型字面值的默认类型;
布尔字面值和指针字面值
true与false;
2.2 变量
变量提供一个具名的、可供程序操作的存储空间;
在c++中,变量跟对象一般可以互换使用;
2.2.1 变量定义
如何定义变量;
初始值
什么是初始化;
初始化不是赋值;
可以用先定义的变量区初始化其他变量;
列表初始化
初始化变量的几种方式;
默认初始化
变量什么时候会被默认初始化;
默认值是由变量类型、变量的位置决定的;
2.2.2 变量声明和定义的关系
为了支持分离式编译,c++将声明与定义区分开;
声明的作用;声明的关键字;
定义的作用;
extern语句如果包含初始值就不再是声明而是定义;
变量定义只能定义一次,声明可以很多次;
2.2.3 标识符
标识符的语法规范;
变量命名规范
4点命名规范;
2.2.4 名字的作用域
名字的有效区域从名字的声明语句开始到声明语句所在的作用域末端为结束;
大多数作用域以花括号分隔;
main函数具有全局作用域;
块作用域的含义;
嵌套的作用域
内层作用域的含义;外层作用域的含义;
外层作用域声明的名字,内层作用域也可以访问到;
作用域操作符::左面为空时代表的是全局作用域;
2.3 复合类型
主要介绍了指针和引用两种复合类型;
一条声明语句由一个基本数据类型和紧随其后的一个声明符列表组成;
2.3.1 引用
引用的定义;
引用一旦声明必须初始化,且会和初始化对象一直绑定在一起;
引用即别名
引用就是所绑定的对象的另一个名字;
引用本身不是对象,所以没有引用的引用;
引用的定义
引用只能绑定在对象上;不能与字面值或者某个表达式的结果绑定在一起;
2.3.2 指针
指针本身就是对象;
同一个指针可以先后指向不同的对象;
定义指针时不必同时初始化;
获取对象的地址
指针存的是对象的地址;
通过取地址符&来获取对象地址;
指针值
 指针的值有4个状态;
 访问没有指向对象的指针的对象是错误的;
 拷贝以及访问无效指针的值都是错误的;
利用指针访问对象
当指针指向对象时,可以用解引用符来访问对象;
空指针
nullptr是特殊类型的字面值,用来初始化空指针;
将int变量赋值为0,再用这个int去初始化指针式错误的;
赋值和指针
无
其他指针操作
指针拥有合法值时,可以作为条件表达式的条件;
可以用2相等操作符==来比较2个指针;
void*指针
void *指针可以存放任意对象的地址;
2.3.3 理解复合类型的声明 定义多个变量
int i = 1024, *p = &i, &r = i;
变量的定义包括一个基本数据类型和一组声明符;
指向指针的指针
int* *p2 = &p1;
*p2表示这是一个指针;int*表示指针指向的是一个int*类型,也就是存储了指向int型指针的地址;
指向指针的引用
指针是对象,所以存在与指针绑定的引用;
也就是指针的别名;
2.4 const限定符
const对象一旦创建就要初始化;
初始化和const
const对象的操作只能执行一些不改变其对象内容的;
可以用非const对象初始化const对象;
默认状态下,const对象仅在文件内有效
const对象只能在本文件内有效;
为了使const在文件间共享,需要extern关键字;
2.4.1 const的引用
与const对象绑定的引用就是常量引用;
初始化和对const的引用
初始化常量引用时可以用任意表达式作为初始值,只要该表达式可以转换成引用的类型即可;
常量引用可以绑定非常量的对象、字面值、一般的表达式;
对const的引用可能会引用一个并非const的对象
常量引用可以绑定一个非常量;
但是不可以通过这个常量引用去修改这个非常量;可以用其他的办法改变这个非常量;
2.4.2 指针和const
可以有指向常量的指针;
指向常量的指针可以指向一个非常量对象;
同常量引用一样,此时不可以通过此指针改变这个非常量对象,但可以通过其他途径改变;
const指针
指针本身可以是常量;
常量指针定义就必须初始化;这个指针一旦定义就不可以改变其中的内容了;
但是常量指针指向的内容可以改变;
2.4.3 顶层const
顶层const表示该对象本身就是一个const;
底层const表示该对象指向或绑定的那个对象是const;
一个例子:指针本身是不是常量与其指向的对象是不是常量是2回事;
执行对象拷贝操作时,顶层const不受影响:因为顶层const可以赋值给非常量;
而底层const不能赋值给非常量指针或者引用,因为其指向或者绑定的对象是常量,
这样会导致权限泄露;
2.4.4 constexpr和常量表达式
常量表达式要满足值不会变、编译过程就得到计算结果这2个条件;
constexpr变量
constexpr的语义是常量表达式;
constexpr变量是常量,且必须由常量表达式初始化;
字面值类型
啥是字面值类型;
指针和constexpr
constexpr将它所定义的对象置为顶层const;
constexpr指针可以指向常量也可以指向非常量;
2.5 处理类型 2.5.1 类型别名
介绍了定义类型别名的2种办法;
别名声明;
指针、常量和类型别名
把类型别名替换成原本的样子是错误的;
2.5.2 auto类型说明符
auto让编译器通过初始值来推算变量的类型;
复合类型、常量和auto
auto会忽略顶层const属性;如果希望推断出来的是顶层const,需要手动添加;
auto&不会忽略顶层const,因为此时已经是底层const了;
当初始值为引用时,编译器会将引用绑定的对象作为auto的类型;
在一条语句定义多个变量时,符号&与*都是只从属于某个声明符;
2.5.3 decltype类型指示符
auto是用该表达式的值作为初始值;decltype则不用表达式的值作为初始值;
decltype使编译器分析表达式的类型,却不实际计算表达式的值;
decltype实事求是,表达式(前提是一个变量)的类型是啥就是啥,与auto不同;
decltype和引用
若表达式不是变量,decltype返回表达式结果的类型;
表达式的内容是解引用操作,则decltype得到一个引用类型;
decltype(())的结果永远是引用;
2.6 自定义数据结构
库类型string、istream、ostream等都是以类的形式定义的;
2.6.1 定义Sales_data类型 类数据成员 2.6.2 使用Sales_data类 添加两个Sales_data对象 Sales_data对象读入数据 输出两个Sales_data对象的和 2.6.3 编写自己的头文件
类一般定义在头文件中;
预处理器概述
预处理器的概念;
头文件保护符的作用;
3 字符串、向量和数组 3.1 命名空间的using声明
std::cin中::的含义是编译器应从操作符左侧名字所示的作用域中寻找右侧那个名字;
使用using就不需要专门的前缀比如std::,就可以使用后面的名字了;
每个名字都需要独立的using声明
每个using声明可以引入命名空间的一个成员;
也可以是整个命名空间的成员都可见;
头文件不应包含using声明
头文件不应该使用using,
因为其他使用这个头文件的文件里的名字可能与头文件using的命名空间里的名字冲突;
一点注意事项
无
3.2 标准库类型string
标准库类型string表示可变长的字符序列;
3.2.1 定义和初始化string对象
初始化类的对象是由类本身决定的;
初始化string对象的一些方式(默认初始化、提供一个字符串字面值、提供一个数字和字符、string对象赋值);
直接初始化和拷贝初始化
使用等号初始化一个变量就是拷贝初始化;
其他的初始化就是直接初始化;
对于初始化需要多个值也可以使用拷贝初始化,不过不利于阅读;
3.2.2 string对象上的操作
介绍了string对象的操作;
读写string对象
输入string对象时,string对象会自动忽略开头的空白从第一个字符开始一直到一个空白为止;
读取未知数量的string对象
while(cin>>str);
使用getline读取一整行;
如果想要保留输入时的空白符就使用getline();
string的empty和size操作
string类的empty函数用来判断string对象是否为空;
string类的size函数用来返回string对象的长度;
string::size_type类型
string类的size函数用来返回string对象的长度的数据类型
是由string类自己定义的(string::size_type);
比较string对象
string类的一些运算符进行比较的一些规则;
为string对象赋值
string类支持一个对象给另一个对象赋值;
两个string对象相加
加法运算符允许2个string对象拼接;
字面值和string对象相加
标准库允许字符字面值和字符串字面值与string对象拼接;
但是字面值之间不可以直接相加;
字符串字面值与string类不是一个类型;
3.2.3 处理string对象中的字符
如何获取string对象的每一个字符?
使用基于范围for语句处理每个字符
基本形式就是:for(循环变量:对象){...};
循环变量用于迭代访问对象中的基础元素;
可以配合auto进行迭代;
使用范围for改变字符串中的字符
如果想改变序列中的每一个元素,只需要把范围for中的循环变量类型变成引用即可;
这样可以使循环变量每次迭代时与序列的元素进行绑定??(引用不是绑定了就改不了了吗?)
只处理一部分字符?
通过使用下标、迭代器来访问string对象的单个字符;
下标运算符[]:接受的输入参数类型是string::size_type;
使用下标执行迭代
可以用普通for循环对string对象通过下标进行迭代;
使用下标执行随机访问
无
3.3 标准库类型vector
vector是一个类模板,表示对象的集合且对象的类型要相同;
模板就是编译器生成类或者函数编写的说明书;
编译器根据模板创建类或者函数的过程叫做实例化;
类模板的格式;
3.3.1 定义和初始化vector对象
介绍了初始化vector对象的方法;
默认初始化;定义vector对象时指定元素的初始值;
列表初始化vector对象
列表初始化也是定义vector对象时指定元素初始值的一种;
拷贝初始化只能提供一个初始值;
提供类内初始值时只能使用拷贝初始化或者花括号的形式初始化;
创建指定数量的元素
无;
值初始化
定义vector对象时可以提供对象容纳的元素数量且略去初始值;
此时库会创建一个值初始化的元素初值,
此时的元素初值是多少取决于vector对象中元素的类型,
如果元素的类型不支持默认初始化,则需要提供初始值;
如果以后更新容器元素的值,只能通过直接初始化;
列表初始值还是元素数量?
vector对象初始化的真实含义取决于传递初始值时用的是花括号还是圆括号;
如果是圆括号,可以说是提供的值来构造vector对象;
如果是花括号,可以说是用来列表初始化(花括号里的值应该与元素类型相同);
如果用的是花括号但是提供的值不能实现列表初始化,
就会考虑用来构造vector对象,并会被默认值初始化;
3.3.2 向vector对象中添加元素
直接初始化适用的3个情况;
当创建vector对象不清楚元素个数时,不适合初始化;
此时适合先创建vector对象再利用push_back()向其添加元素;
push_back()函数是vector模板的成员函数;
向vector对象添加元素蕴含的编程假定
当循环体内部包含向vector对象添加元素的语句时,不可以使用范围for语句;
范围for语句体内不可以改变其所遍历序列的大小;
3.3.3 其他vector操作
介绍了vector支持的其他操作;
vector的size函数的返回类型是vector<数据类型>::size_type
计算vector内对象的索引
可以通过下标运算符[]来访问vector对象的某一个元素;
下标的类型是相对应的size_type类型;
不能用下标形式添加元素
vector对象的下标运算符只可访问已经存在的元素,不可以用来添加元素;
3.4 迭代器介绍
string虽然不是容器但是支持迭代器;
迭代器提供对对象的间接访问;
迭代器要不指向某个元素,要不指向容器中尾元素的下一个位置,其他都是无效的;
3.4.1 使用迭代器
有迭代器的类型都拥有返回迭代器的成员;
begin成员负责返回指向第一个元素的迭代器;
end成员负责返回容器尾元素的下一位置;
迭代器运算符
介绍了迭代器支持的运算;
解引用一个非法迭代器或者尾后迭代器都是未定义的行为;
解引用迭代器得到的是迭代器所指元素的引用;
将迭代器从一个元素移动到另外一个元素
迭代器的递增或者递减的意思是将迭代器向前或后移动一个位置;
利用循环+auto可以依次访问操作每一个元素;
迭代器类型
使用iterator以及const_iterator来表示迭代器的类型;
每个容器类型以及string类定义了名为iterator类型;
const_iterator与常量指针差不多,仅仅可以访问不可以修改;
begin和end运算符
begin和end返回的类型由对象是不是常量决定;
有的对象仅需要读操作,此时最好使用常量类型;
cbegin、cend成员无论vector本身是否为常量均返回const_iterator类型;
结合解引用和成员访问操作
解引用迭代器会得到其指向的对象,若此时为类类型,可进一步得到其成员;
箭头运算符将解引用和成员访问两个操作结合在一起;
某些对vector对象的操作会使迭代器失效
任何改变容器容量的操作会使其迭代器失效;
3.4.2 迭代器运算
介绍迭代器的一些运算;
迭代器的算术运算
两个迭代器相减得到的数据的类型是difference_type的带符号整型数;
此类型vector和string都定义了;
使用迭代器运算
介绍了一个程序利用迭代器进行二分搜索;
3.5 数组
与容器相比,数组大小固定,容器比较灵活;
3.5.1 定义和初始化内置数组
数组是复合类型;
数组元素的个数也属于数组类型的一部分;
数组的维度必须是一个常量表达式;
默认情况下,数组被默认初始化;
数组的元素应该是对象,所以不存引用;
定义数组时不允许用auto等推断类型;
显示初始化数组元素
数组可以列表初始化;
一些初始化数组的方式;
字符数组的特殊性
字符数组可以用字符串字面值去初始化;
此时字符数组会自动存储空字符(表示字符串结束);
不允许拷贝和赋值
无;
理解复杂的数组声明
无;
3.5.2 访问数组元素
数组的元素可以通过范围for、下标运算符进行访问;
使用数组下标时,其数据类型为size_t,在cstddef头文件定义了;
检查下标的值
下标应大于等于0小于数组的大小;
3.5.3 指针和数组
取地址符可以用于任何对象;
很多情况下,编译器会自动将数组名转换为指向该数组首元素的指针;
当将数组名作为auto变量的初始值时,推断的类型为指针;
当用decltype推断时不会发生转换,还是数组;
指针也是迭代器
vector和string的迭代器支持的运算,数组的指针都支持;
使用指针可以迭代数组,需要指向首元素的指针,以及尾元素下一个地址的指针;
指向首元素的地址的指针已知,指向尾元素下一个地址的指针需要利用下标运算符去得到;
标准库函数begin和end
c++11引入begin和end函数获得首指针以及尾后指针(安全);定义在iterator头文件;
因为数组不是类类型,所以这俩不是成员函数而是普通函数;
因此调用方式不同;
指针运算
2个指针相减的结果的数据类型是ptrdiff_t;
定义在cstddef头文件中;
带符号类型;
解引用和指针运算的交互
无;
小标和指针
标准库类型限定使用的下标是无符号类型;
内置的下标可以是负数;
3.5.4 C风格字符串
c风格字符串不是类型而是一个写法;
此字符串存在字符数组中并以空字符结束;
C标准库String函数
C风格字符串的一些函数;
比较字符串
与string类型不同;
使用strcmp来比较;
目标字符串的大小由调用者指定
c风格字符串若想拼接需要3步;
3.5.5 与旧代码的接口 混用string对象与C风格字符串
任何出现字符串字面值的地方都可以用以空字符结束的字符数组来替代;
此结论反过来不行;
使用数组初始化vector对象
vector不可以初始化数组,但是数组可以初始化vector;
只需要指明首元素地址和尾后地址即可;
用于初始化vector对象的值也可能仅仅是数组的一部分;
3.6 多维数组
多维数组通常用2个维度定义:一个维度表示数组本身大小,一个维度表示其元素大小;
对于2维数组来说,第一个维度是行,第2个维度是列;
多维数组的初始化
介绍了初始化方式;
多维数组的下标引用
使用下标运算符来访问多维数组的元素;
使用范围for语句处理多维数组
为了避免数组自动转换指针,我们需要把外层循环的控制变量声明为引用类型;
指针和多维数组
多维数组名转换的指针实际是指向第一个内层数组的指针;
类型别名简化多维数组的指针
无;
4 表达式 5 语句 6 函数 6.1 函数基础
函数的组成部分包括:返回类型 函数名字 形参组成的列表 函数体
通过调用运算符()执行函数;调用运算符的形式、作用对象等
编写函数
案例程序实现1到n的阶乘:返回类型是int、函数名字是fact、形参接受一个int参数
调用函数
函数调用完成2件事情:实参初始化函数的形参、控制权移交给被调函数;
主调函数、被调函数;
遇到return语句函数结束执行过程:返回return语句的值;控制权还给主调函数
形参和实参
实参与形参的类型要匹配、数量要相同
函数的形参列表
形参列表的语法格式
隐式以及显示的表示形参为空
函数返回类型
特殊的返回类型void
函数的返回类型不可以是数组、类,但可以是指向数组、函数的指针
6.1.1局部对象
名字的作用域以及对象的生命周期的概念
局部变量:形参以及函数体内部定义的变量
局部变量会隐藏在外层作用域中同名变量
局部变量的声明周期取决于定义的方式
自动对象
自动对象:只存在于块执行期间的对象
局部变量对应的自动对象初始化分为种情况:如果变量有初始值就用此初始值初始化,
若变量定义本身不含有初始值,执行默认初始化
内置类型的未初始化变量将产生未定义的值
局部静态对象
有必要使局部变量的生命周期贯穿函数调用开始到整个程序结束才销毁(使局部变量不受块的约束)
,此时将局部变量定义成static类型即可
6.1.2 函数声明
函数声明包括返回类型 函数名、形参类型也称为函数原型
在头文件中进行函数声明
在头文件声明函数、在源文件中定义函数
含有函数声明的头文件应该被包含在定义函数的源文件中
编译器负责验证函数的定义与声明是否匹配
6.1.3 分离式编译
分离式编译允许把程序分割在各个文件、每个文件独立编译
编译和链接多个源文件
先把各个.cpp文件编译成.o文件,
然后将这些.o文件(该文件包含对象代码)
链接起来形成.exe文件
修改了某个源文件只需重新编译改动的源文件
6.2 参数传递
形参的类型决定了形参和实参的交互方式
6.2.1 传值参数
形参是非引用类型变量时,函数对形参的所有操作不会影响实参
指针形参
执行拷贝指针操作时,拷贝的是指针的值,就是说这两个指针指向的内容是同一个,
因此可以改变所指向的对象的内容
6.2.2 传引用参数 使用引用避免拷贝
当拷贝的内容大比如类类型对象或者容器对象、或者拷贝的对象不支持拷贝操作,
那么此时用引用形参访问该类型对象比较好
当函数不改变引用形参的值时,要将其声明为常量引用
使用引用形参返回额外信息
可以通过额外传入一个引用实参来实现返回额外的信息
6.2.3 const形参和实参
当形参是顶层const时,传给它常量对象或者非常量对象都是可以的,此时忽略了形参的顶层const
因此对于相同名字的函数中,形参类型为const与int const是重复的
指针或引用形参与const
形参的初始化与变量的初始化的方式是一样的,规则也是
底层const可以用非常量初始化,而底层const不能初始化非常量
字面值可以初始化常量引用
尽量使用常量引用
我们不能把const对象、字面值、或者需要类型转换的对象传递给普通的引用形参
6.2.4 数组形参
数组不允许拷贝、使用数组时,数组名会转化为指针并指向数组首元素
不能以值传递的方式传递数组,我们可将形参写成类似数组的形式
使用标记指定数组长度
这种办法适用那些有明显结束标记的内容,比如c风格的字符数组(末尾以空字符结束)
使用标准库规范
使用begin()与end()向函数传递指向数组首元素以及尾元素下一个位置的指针
显示传递一个表示数组大小的形参
将begin()与end()想减得到数组大小,再向函数传递此参数即可
数组形参和const
当函数不需要对数组元素进行改变时,要将形参定义成const类型
数组引用形参
形参可以是数组的引用,比如:int (&arr)[10] 注意括号,维度是类型的一部分
传递多维数组
比如 int (*arr)[10]:arr是一个指针指向一个数组包含10个int 
6.2.5 main:处理命令行选项
main函数接受2个参数分别是int argc(表示数组中字符串数量)
以及 char *argv[](其元素是指向c风格字符串的数量)
6.2.6 含有可变形参的函数
若函数的实参数量未知且类型相同,我们可以使用initializer_list的形参
省略符形参
用于c++程序访问c代码设置的
6.3 返回类型和return语句
return语句的作用以及格式
6.3.1 无返回值函数
返回类型为void的函数
6.3.2有返回值函数
return语句返回值的返回类型要么与函数的返回类型相同,要不可以隐式转换成函数的返回类型
值是如何被返回的
返回值用于初始化调用点的一个临时量
返回一个值的方式与初始化一个变量或者形参的形式是一样的
不要返回局部对象的引用或指针
当函数结束时,函数内所定义的变量将会销毁,所以返回的如果是局部变量的引用或者指针
将会指向不再可用的内存空间
返回类类型的函数和调用运算符
当返回类型是一个类类型、指针、引用时,就可以通过对返回结果打.来访问结果对象的成员
引用返回左值
函数的返回类型决定函数调用是否是左值
返回类型是引用时,得到左值,其他为右值
列表初始化返回值
函数可以返回花括号包围的值的列表
主函数main的返回值
main函数可以没有return直接结束
因为编译器可以隐式地插入一条返回0的return语句
返回0代表执行成功,其他为失败
cstdlib文件定义2个预处理量表示函数执行成功还是失败
递归
啥是递归
可以利用return语句实现递归
递归循环的意思
6.3.3 返回数组指针
由于数组不可以被拷贝,所以若想返回一个数组,其解决办法是返回一个指向数组的指针或引用
由于语法上,定义一个返回类型是数组指针或者数组引用比较繁琐,最简单的就是使用类型别名
声明一个返回数组指针的函数
若不用类型别名该怎么声明?
记住数组的维度要在定义的数组名之后
比如: int(*func(int i))[10]
使用尾置返回类型
这个办法比较简单
为了表示函数真正的返回类型在形参列表以后,我们要在本该出现返回类型的地方放置auto
比如 auto func(int i) -> int(*)[10]
使用decltype
若我们知道函数返回的指针指向的具体数组,就可以使用decltype声明返回类型
decltype不负责把数组类型转为指针,所以自己要主动加*符号
6.4 函数重载
重载函数的概念
编译器根据传递的实参类型推断想要哪个重载函数
定义重载函数
只有返回类型不同,其他都相同的函数是不被允许的
判断2个形参的类型是否相异
形参的名字可以隐藏
形参可以使用类型别名
重载和const形参
拥有顶层const的形参与没有const的形参是无法区分的,是等价的
形参是指针或引用时,可以通过检查指向的对象是否为常量来区分是否为新函数,此时为底层const
const_cast和重载
const_cast可以改变底层const;
返回类型以及形参都是底层const的函数可以接受一个非常量实参,但返回的仍然是底层const;
要想使返回的是非常量,可以使用const_cast;
首先构造一个形参为非常量的函数,函数体内对形参使用const_cast,将形参转化为底层const,
在返回的时候再使用const_cast;将底层const转回非常量
调用重载的函数
函数匹配(重载确定)的概念
编译器首先将调用的实参与重载函数集合重的每一个函数的形参作比较,根据比较的结果决定调用哪个函数;
当2个重载函数形参数量相同且参数类型可以相互转换时,应该如何选择函数呢?
最佳匹配、无匹配、二义性调用
6.4.1 重载与作用域
内层作用域中声明名字,它将隐藏外层作用域中声明的同名实体;
不同作用域中无法重载函数名;
在当前作用域中找到所需名字,编译器就会忽略外层作用域中的同名实体;
6.5 特殊用途语言特性 6.5.1 默认实参
默认实参的概念,如何使用;
一旦某个形参被赋予了默认值,它后面所有形参都必须有默认值;
使用默认参数调用函数
默认实参调用函数的几个例子;
尽量让不怎么使用默认值的形参放在前面,经常使用的放在后面;
默认实参声明
给定作用域下,一个形参只能被赋予一次默认实参;
函数的后续声明只能给没有默认值的形参添加默认实参;
默认实参初始值
局部变量不可作为默认实参;
表达式的类型可以转化成形参所需类型,就可作为默认实参;
6.5.2 内联函数和constexpr函数
调用函数一般比求等价表达式的值要慢一些
内联函数可避免函数调用的开销
内联函数是啥;
如何声明内联函数;
constexpr函数
啥是constexpr函数;
constexpr函数被隐式地指定为内联函数;
把内联函数和constexpr函数放在头文件内
无
6.5.3 调试帮助 assert预处理宏
asset宏常用来检查“不能发生的条件”;
条件为真则继续执行文件内程序;
条件为假则终止程序的运行;
NDEBUG预处理变量
NDEBUG能避免检查各种条件所需运行的开销;
assert依赖于NDEBUG的状态;
NDEBUG自己也可以进行条件调试代码;
介绍了5个编译器定义的局部变量;
6.6 函数匹配 确定候选函数和可行函数
啥是候选函数、啥是可行函数;
寻找最佳匹配
函数匹配的第3步时从可行函数中选择与本次调用最匹配的函数;
基本思想是:实参类型与形参类型越接近,其匹配的越好;
精确匹配比需要类型转换的匹配更好;
含有多个形参的函数匹配
当实参数量有2个或者更多时,函数匹配原则没有改变,但是比较复杂;
6.6.1 实参类型转换
实参类型转换到形参类型的几个等级:
精确匹配>通过const转换实现的匹配>类型提升实现的匹配>算术类型实现的匹配>类类型转换实现的匹配;
需要类型提升和算术类型转换的匹配
无
函数匹配和const实参
无
6.7 函数指针
函数指针的概念;
函数的类型只与返回类型以及形参类型有关;
使用函数指针
当我们把函数名当作值来使用时,该函数会自动转换成指针;
可以直接使用指向函数的指针调用该函数,不需要提前解引用指针;
指向不同函数类型的指针间不存在转换规则;
重载函数的指针
指向重载函数的指针类型必须与重载函数中的某一个精确匹配;
函数指针的形参
形参可以是指向函数的指针(看上去是函数类型,却被当成指针使用);
函数可以直接当实参,此时该函数名自动转化为指针;
可以使用类型别名或者decltype来简化函数指针;
返回指向函数的指针
函数的返回类型不可以返回函数但是可以返回指向函数的指针;
编译器不会自动的把函数返回类型当成对应的指针处理,所以我们要把返回类型写成指针形式;
可以使用类型别名来声明返回类型为指向函数的指针;
也可以使用尾置返回类型的方式声明;
学会读返回类型为函数指针的函数的声明;
将auto和decltype用于函数指针类型
decltype也可的前提是明确返回的函数是哪一个;
此时记得显示的添加*表明我们需要返回的是指针;
7 类
类的基本思想是数据抽象和封装;
7.1 定义抽象数据类型
sales_item类是一个抽象数据类型,而sales_data并不是;
因为sales_data类允许类的用户直接访问它的数据成员;
若想将其变成抽象数据类型,我们应该定义一些操作;
7.1.1 设计Sales_data类
设计了此类应该具有的操作;
使用改进的Sales_data类
介绍如何使用此类;
7.1.2 定义改进的Sales_data类
成员函数必须声明在类内部,定义在类外内部均可;
接口组成部分的非成员函数的定义与声明在类外部;
定义成员函数
无
引入this
成员函数通过this隐式参数来访问调用它的对象;
当调用一个成员函数时,用请求该函数的对象的地址去初始化this;
this是一个常量指针;
引入const成员函数
this是指向类类型非常量版本的常量指针;
因此当常量对象调用普通的成员函数时,无法用this;
此时可以将this声明为指向const类类型即可;
此时要把const声明在函数形参列表之后以表示this是一个指向常量的指针(常量成员函数);
类作用域和成员函数
编译器分两步处理类:首先编译成员的声明,然后编译函数体;
因此函数体内可以随意使用类中的其他成员;
在类的外部定义成员函数
在类外部定义函数时,要求成员函数的定义要与其声明匹配;
返回类型、参数列表和函数名要求与类内部的声明一致;
类外部定义的成员的名字必须包含它所属的类名;
定义一个返回this对象的函数
解引用this指针即可获得调用此函数的对象;
若想让函数返回值当作左值使用,应该将函数返回类型设置为引用;
7.1.3 定义类相关的非成员函数
若函数在概念上属于类,但是不定义在类中,一般应与类声明(不是定义)在同一个头文件中;
定义read和print函数
io类属于不可以被拷贝的类型,因此只能使用引用来传递他们;
由于输入输出操作会改变流的内容,所以是普通引用;
定义add函数
介绍了add函数的功能;
7.1.4 构造函数
每个类都分别定义了它的对象被初始化的方式:构造函数;
构造函数的特点:与类名同名;无返回类型;类可包含多个;不同构造函数间参数数量或类型必须不同;
合成的默认构造函数
类通过合成的默认构造函数来默认初始化类类型对象;
默认构造函数初始化类的规则;
某些类不能依赖于合成的默认构造函数
合成的默认构造函数只在编译器发现类没有其他构造函数才会生成;
由于在块内的内置类型或者复合类型的对象被默认初始化则他们的值是未定义的,
所以含有这类型的类需要自己定义默认构造函数;
若类中还有其他类类型恰巧没有默认构造函数,则此时编译器无法默认初始化此类;
综上我们要自己构建默认构造函数;
定义Sales_data的构造函数
无;
=default的含义
此方式用于生成默认构造函数;
可以定义在类内部,也可类外部;
在类内部是内联的,外部则不是;
构造函数初始值列表
介绍了构造函数初始值列表的语法格式;
当某个数据成员被构造函数初始值列表忽略时,它将以合成默认构造函数相同的方式隐式初始化;
在类的外部定义构造函数
构造函数初始值列表为空时,可能函数体里会初始化,
没有初始化的数据成员将通过类内初始值初始化,或者执行默认初始化;
7.1.5 拷贝、赋值和析构
除了定义类的对象的初始化,还需控制拷贝、赋值、和销毁对象;
某些类不能依赖于合成的版本
当类需要分配类对象之外的资源时,合成的版本就会失效(拷贝、赋值、销毁);
当类包含vector或者string成员时,则其合成的版本是有效的;
7.2 访问控制与封装 7.3 类的其他特性 7.4 类的作用域 7.5 构造函数再探 7.6 类的静态成员
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1009337.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号