C++ Primer chap-1&chap-2&chap-3&chap4&chap5&chap6&chap7

正式开始啃这部C++圣经
打算看的部分:
通读的部分:
1-7 9 11 12.1 13 16.1
了解的部分:
10 12.2 14 15 16其他部分

其他先不看。
只对于自己不熟悉的地方做笔记
冲!

chapter 1
1.1 一个简单的C++程序

1.2 初始输入输出
输入输出都是返回其左值对象
cerr 输出警告
clog 输出程序运行的一般性信息

1.3 注释简介

1.4 控制流
for循环定义了局部的变量
for循环体每次执行之前先检查循环条件
读取数量不定的输入数据
while(cin>>value)
上面这一句检测的左值运算对象 cin,也就是检测istream流的状态
流未遇到错误,则检测成功(文件结束符或者无效输入则istream状态无效)
文件结束符:Windows:ctrl+z unix:ctrl+d
经验:按照报告的信息来解决错误!由于编译器可能报告比你存在的错误多得多的错误信息。

1.5类简介

1.6书店程序

第一章的东西还很基础,不详细写了。

chapter 2 变量和基本类型
2.1 基本内置类型
p30 各个类型占的大小 int 16位(大多数都是16)
字节:可寻址的最小内存块(大多数8bit)
字:多个字节组成(大多数32bit or 64bit)
无符号类型转换时的问题p33 34
字符串编译器在结尾还会加一个空字符

------没保存!!!卧槽!!
以后再补档,烦死了!!

2.6.3
头文件通常包含那些只能被定义一次的实体,如类,const,constexpr变量
确保头文件多次包含仍能安全工作的常用技术是预处理器
预处理器看到#include标记就会用指定的头文件的内容代替#include
一项预处理功能:头文件保护符
#define 把一个名字设定为预处理变量
#ifdef 当且仅当变量已定义为真
#ifndef 当且仅当变量未定义为真
#endif 检查结果为真 执行后续操作一直到遇见#endif
预处理变量包括头文件保护符必须唯一。

感慨:以前博客查到的杂七杂八的知识不如一本C++ Primer通读一遍来的快,根基不牢,地动山摇。

chapter3 字符串,向量,和数组
3.1
头文件不应包含using声明
3.2 标准库类型string
string的几种初始化 p76(直接和拷贝不同)
3.2.2
使用getline读取一整行(可以读取空白符)
string line;
while(getline(cin,line)){}
string ::sizetype类型
string的比较按照字典顺序
如果s1字符串是s2的一个子集,那就是s1<s2
如果在某些位置不一样,就比较第一个不同的字符的字典顺序
string s6=s1+","+“world”; 这是正确的!
string s7=“hello”+","+s2;错误!
切记:字符串字面值和string是不同的类型!
3.2.3
cctype头文件中的函数 判断字符的类型 p82
string中的for遍历
改变字符时 用引用 auto&
只处理一部分字符:
1.下标运算符 0—s.size()-1
总是得检查下标的合理性!一种简便的办法是总是设下标的类型为string::size_type.

2.迭代器

3.3
vector初始化
列表初始化 区分圆括号花括号
3.3.2
push_back
如果循环体包含向vector添加对象的语句就不能用for循环
3.3.3
auto&也是可以的 取得元素引用用于赋值的时候用!
不能用下标形式添加元素,只能对已存在的元素进行下标操作!

3.4 迭代器介绍
begin() 返回指向第一个元素的迭代器
end() 返回指向最后一个元素后一位的迭代器
迭代器运算符 * --> ++ – == !=
泛型编程
cbegin()和cend()也返回同一位置迭代器,不同的是返回值是const_iterator
为了简化例如(*it).empty()这样的表达式,C++定义了箭头运算符(->)
it->men相当于(*it).mem
任何一种可能改变vector容量的操作都会使迭代器失效。
3.4.2迭代器运算
二分搜索看一下
3.5数组
字符数组 当用字符串字面值赋值的时候要记得最后还有一个空字符
数组不允许拷贝和赋值(标准特性) 这样来看vector比起来简直好用不知多少

int *ptr[10];//含有十个整形指针的数组
int &refs[0]=/ * ? */;//错误 不存在引用的数组
int (*Parray)[10]=&arr;// Parray指向一个含有10个整数的数组
int (&arrRef)[10]=arr; //arrRef引用一个含有10个整数的数组
对于数组而言,我们由内而外而非从右到左阅读更能理解它的含义(说白了怎么记住怎么来 = =)
int *(&arry)[10]=ptrs; //arry是数组的引用,该数组含有10个指针(我太难了)
3.5.2
检查下标永恒的主题
3.5.3
很多用到数组名的地方,编译器会自动地将其替换为一个指向数组首地址的指针。
标准库函数begin和end(C++)
int *p=begin(ia);
int last= * (ia+4);//last初始化为ia[4]的值
只要指针指向的是数组的元素(以及tail),都可以执行下标运算,看以下代码(震惊我全家)
int p=&ia[2];//p指向索引为2的元素
int j=p[1];//p[1]等价于
(p+1),也就是ia[3]表示的元素
int k=p[-2];//p[-2]是ia[0]表示的那个元素
可以发现内置的下标可以是负数,跟vector string不同.
3.5.4 C风格字符串(不建议使用)
C风格字符串的函数 strlen§ strcmp(p1,p2) strcat(p1,p2) strcpy(p1,p2)
传入此类函数的指针必须是指向以空字符作为结束的数组!
比较C风格字符串和连接拷贝都区别很大,总而言之,不建议使用!
3.5.5与旧代码的接口
主要是string与vector和以前的C风格字符串以及数组的衔接问题
可以用数组来初始化vector
3.6 多维数组
多维数组说的就是数组的数组
初始化的办法
使用范围for语句处理多维数组
除了最内层的循环外,其他所有循环的控制变量都应该是引用类型
int *ip[4]; //整形指针的数组(数组里面都是指针)
int (*ip)[4];//一个指针,指向含有四个整数的数组(杀了我吧)

chapter 4 表达式
4.1基础
左值和右值
当一个对象被用作右值的时候,用的是对象的值(内容),当对象被用作左值的时候,用的是对象的身份(内存中的位置)
赋值运算符得到的结果仍然是一个左值
取地址符作用于左值返回右值(一个指向该对象的指针)
解引用,下标运算符求值结果是左值
内置类型和迭代器的递增递减运算符作用于左值,返回的也是左值。
假定p的类型是int
解引用生成左值
decltype(p)返回的是int&
取地址符生成右值
decltype(&p)结果是 int
*,也就是该指针的地址,也就是个二级指针
4.1.2优先级与结合律
4.1.3求值顺序
有四种运算符规定了运算对象的求值顺序
&& || ?: 和逗号,
4.2 算术运算符
m%(-n)等于m%n (-m)%n等于 -(m%n)
4.3 逻辑和关系运算符
&&和||都是短路求值
4.4赋值运算符
赋值运算符满足右结合律 返回的是左值
赋值运算符的优先级较低 p130的例子可以看一下
复合赋值运算符
4.5 递增和递减运算符
前置版本(++i)
将运算对象加(减)一,将改变后的对象作为求值结果(该对象作为左值返回)
后置版本(i++)
将运算对象加(减)一,求值结果是对象改变之前的那个副本(作为右值返回)
除非必须,不用后置版本!!
形如*pbeg++ 这样简洁的形式要习惯使用
4.6 成员访问运算符
ptr->mem等价于(*ptr).mem
4.7 条件运算符
嵌套条件运算符
4.8 位运算符
移位运算符
位求反运算符
位与,位或,位异或
使用位运算符(这个例子挺有趣)
移位运算符满足左结合律
4.9 sizeof运算符
返回一条表达式或一个类型名字所占的字节数
sizeof并不实际计算运算对象的值,满足右结合律
对char执行sizeof 结果为1
对引用类型执行sizeof 得到被引用的对象所占空间的大小
对指针执行dizeof得指针本身所占空间的大小
对解引用执行sizeof的指针指向的对象所占空间大小,指针无需有效
sizeof不会把数组转成指针处理,会返回数组所占空间的大小
对string或vector对象执行sizeof之返回该类型固定部分的大小
sizeof返回值是常量
4.10逗号运算符
常用于for循环中
4.11类型转换
隐式转换发生的情况p141
整型提升
无符号类型的运算对象(主要是有符号和无符号运算的类型转换)
其他几种隐式类型转换
强制类型转换(危险)
1.命名的强制类型转换
cast-name(expression)
static_cast 一般都可以用 只要没底层const
const_char 只能用来改变运算对象的底层const
reinterpret_cast 为运算对象的位模式提供较低层次上的重新解释(很危险,表面上改了,实际上是奸细)
2.旧式的强制类型转换
type(expr)或者(type)expr
相当于没有显示地区分类型转换的类型,难以追踪可能错误。
4.12 运算符优先级表

chapter 5 语句
5.1 简单语句
5.2 语句作用域
5.3条件语句
悬垂else问题
switch匹配成功会从匹配的case开始依次执行到最后,所以需要break;
5.4迭代语句
for语句init-statemem可以有多个定义,只能有一条声明语句。
再复习下声明和定义的区别:
变量定义:用于为变量分配存储空间,还可为变量指定初始值。程序中,变量有且仅有一个定义。
变量声明:用于向程序表明变量的类型和名字。
定义也是声明,extern声明不是定义
范围for语句
for(declaration:expression)
statement
一般用这个来遍历所有元素。 auto比较好用
不能通过范围for语句来增加vector的元素
5.5跳转语句
break; continue; goto; return;
5.6 try语句块和异常处理
1.throw表达式
throw runtime_error(" ");
2.try…catch
try
{//代码
}
catch(异常声明)
{
}
catch()
{
}//…
3.异常类
exception exception 默认初始化
stdexcept
new bad_alloc 默认初始化
type_info bad_cast 默认初始化
what()函数 指向C风格字符串的 const char*

chapter 6 函数
6.1函数基础
局部静态变量
函数声明(可定义一次声明多次)又称函数原型
分离式编译
6.2参数传递
6.2.1传值参数
指针形参
6.2.2 传引用参数
使用形参返回额外信息
const形参和实参
数组形参,传过去一般不知道size,有以下几种办法
1.使用标记(比如C风格字符串最后一个是空)
2.使用标准库规范(beg,end,传数组的首尾指针)
3.显示传递(把size传过去)
int *matrix[10]; //10个指针构成的数组
int(matrix)[10]; //指向含有10个整数的数组的指针
同理还有:
int &arr[10];//引用的数组
int(&arr)[10];//具有10个整数的整型数组的引用
6.2.5 main:处理命令行选项
假定main函数位于可执行文件prog之类
我们可以向程序传递这样的选项
prog -d -o ofile data0
int main(int argc,char
argv[])
argc表示数组中字符串的数量,第二个形参是数组,元素是指向C风格字符串的指针。
当实参传给main函数之后,argv的第一个元素指向程序的名字或者一个空字符串,接下来的元素依次传递命令行提供的实参。最后一个指针的元素值保证为0.
以上面的命令行为例,argc等于5
argv[0]=“prog”;//或者argv[0]也可以指向一个空字符串
argv[1]="-d";
argv[2]="-o";
argv[3]="“ofile;
argv[4]=“data0”;
argv[5]=“0”;
可选的实参从argv[1]开始,argv[0]保存程序的名字而非用户输入!
6.2.6 含有可变形参的函数
initialize_list也是一种模板类型,它的元素永远是常量值,我们无法改变。
void error_msg(initialize_list il)
{
for(auto beg=il.begin();beg!=il.end();beg++)
cout<<*beg<<” ";
cout<<endl;
}
省略符形参
便于C++访问某些特殊的C代码而设置,使用了varargs的C标准库。
6.3 返回类型和return语句
无返回值函数
有返回值函数
含有return语句的循环后面应该也有一条return语句。
不要返回局部对象的引用或指针
引用返回左值
列表初始化返回值
主函数main的返回值
返回0表示执行成功
递归
6.3.3返回数组指针
int *p1[10];//10个指针的数组
int (*p2)[10]=&arr;//p2是一个指针,它指向含有10个整数的数组。
int(*func(int i))[10];
上面例子太操蛋 p205
使用尾置返回类型,这个就看的很清楚
auto func(int i) ->int( *)[10];
使用decltype这个也不错,多加一个 表示指向数组的指针。
6.4 函数重载
同一作用域,函数名字相同,形参不同
编译器根据实参的类型决定调用哪一个
不允许两个函数除了返回值不同其他都一样!
重载和const形参
一个拥有顶层const的形参无法和另一个没有顶层const的形参区分,
底层const可以
const_cast和重载
调用重载函数三种结果
1.最佳匹配
2.无匹配
3.二义性调用
6.4.1重载与作用域
在局部作用域声明一个函数之后会忽略作用域外部的函数声明
6.5 特殊用途语言特性
6.5.1 默认实参
在形参列表直接给它初始化,在调用的时候可以覆盖掉它。
但是一个注意的点是不能省略前面的赋值后面的,当你想自定义第三个默认形参,前面两个也要定义出来。
默认实参声明
默认实参初始值
6.5.2内联函数和constexpr函数
由于调用函数其实比等价的表达式要慢一点,包含了调用前保存寄存器,在返回时恢复,拷贝实参,程序转向一个新的位置等操作。
内联函数可避免函数调用的开销
就是在函数之前加关键字inline,相当于把函数的语句内联到当前语句中了,避免了诸多调用的时间。
constexpr函数 隐式内联
返回值和所有形参的类型都得是字面值类型。
constexpr函数的返回值不一定是常量表达式。
把内联函数和constexpr函数放在头文件内
基于多个定义必须完全一致,经常展开的考虑。
6.5.3 调试帮助
程序的一些包含调试的代码,发布时应该屏蔽掉调试代码
assert预处理宏、
assert(expr)
表达式为假 输出信息终止程序执行
表达式为真,什么也不做。
NDEBUG预处理变量
6.6 函数匹配
确定候选函数和可行函数
寻找最佳匹配
含有多个形参的函数匹配
6.6.1 实参类型转换
需要类型转换和算术类型转换的匹配
函数匹配和const实参
6.7函数指针
函数指针指向的是函数而非是对象
bool (
pf)(const string&,const string&)
不写这个括号,pf是一个返回值为bool的函数
使用函数指针
我们把函数名当作一个值使用时,该函数自动转化为指针。
我们可以用指向函数的指针直接调用该函数,不必解引用。
重载函数的指针
函数指针形参
虽然不能定义函数类型的形参,但是形参可以是指向函数的指针
返回指向函数的指针
将auto和decltype用于函数的指针

chapter 7 类
7.1 定义抽象类型
7.1.1 设计sales_data类
7.1.2 定义改进的sales_data类
定义成员函数
所有成员必须在类的内部声明,但是成员函数可以定义在类内也可以定义在类外。
引入this
任何对类成员的访问都被看做this的隐式引用,this的目的总是指向“这个”对象,所以this是一个常量指针。
引入const成员函数
类作用域和成员函数
在类的外部定义成员函数
定义一个返回this对象的指针
7.1.3定义类相关的非成员函数
定义read和print函数
定义add函数
7.1.4 构造函数

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值