第一章
- 变量,具有名字的对象
- 缓冲区,一个存储区域,用于保存数据。IO设施通常将输入输出数据保存在一个缓冲区中。
- 文件结束符(end of file, EOF),文件结束标志,通常是-1。
- 初始化,对象创建的时候给它一个初始值。
- 未初始化的变量,没有给定初始值的变量,类类型的变量如果没有指定初值,按类定义指定的方式进行初始化。函数内部的内置类型变量默认是不初始化的,需要进行显式的初始化。
第二章
-
无法预知的行为,编译器无须或者不能检测的错误。即使代码编译通过了,如果程序执行了一条未定义的表达式,仍有可能产生错误,而且这是很有可能的。
-
字面值常量:
12
,024
,0x3
,true
,3.141
,nullptr
,A
都是字面值常量,他们分别属于int
,int
,int
,bool
,double
, 指针,char
等类型。可以通过前缀或者后缀显式的指定字面值的类型,字符和字符串的字面值类型通过前缀指定,整形和浮点型的字面值类型通过后缀指定。 -
字面值类型:算术类型,引用和指针都属于字面值类型,
string
,IO库和类不属于字面值类型。算术类型包含整形和浮点型,整形中又包含字符和int
,long
等。constexpr
只能用于字面值类型。 -
在将有符号数转化为无符号数的时候,如果这个有符号数是负数,那么会做一个模运算,将它转换为正值。
-
有符号数永远不可能为负。
-
不要混用无符号类型和有符号类型,因为有符号数会被转化成有符号数进行运算。
1
2
3
4
5
6
7
8
9
10
11int a = -3;
unsigned int b = 0;
b --;
std::cout << b << std::endl;
b = a;
std::cout << b << std::endl;
b = 3;
std::cout << a* b << std::endl; -
不要用
char
进行算术运算,因为不同的平台实现可能不同,有的是无符号的,有的是有符号的。 -
常见的未定义行为:
-
1
2int i = 1;
i = i++; -
给带符号数一个超出它表示范围的值。
-
默认初始化,变量没有指定初值,被赋予默认值。默认值由变量类型和变量位置决定。
对于内置类型的变量,如果没有显式初始化,它的位置由定义的位置决定。函数内部的内置类型不会被初始化,定义于任何函数外部的内置类型被初始化为$0$。未初始化的变量的值是未定义的。
对于自定义的类型来说,每个类决定初始化对象的方式,而且是否允许不经过初始化就定义对象也由自己决定。如果类允许这种行为,由类决定对象的初始值是什么;如果类要求每个对象显示初始化,在创建类对象没有进行明确的初始化操作时,会引发错误。 -
未初始化变量。
-
声明和定义的区别和联系。
-
在函数体内部不能初始化由
extern
关键字标记的变量。 -
静态类型,在编译阶段检查类型。
-
类型修饰符:
*
和&
,它是声明符的一部分,const也是类型修饰符。 -
声明符:变量名或者变量名前面加上类型修饰符,即
*d
和&d
,其中d
是变量名。 -
复合类型:基于其他类型定义的类型,引用和指针都是复合类型。
-
引用就是别名,不能更改,必须初始化。
-
指针存放的是某个对象的地址,要想获取变量的地址,使用
&
符号获取变量的地址。 -
建议初始化所有指针。如果指针未经初始化,该指针变量中存放的值被当做一个地址,访问该指针,相当于访问一个本不存在的变量,如果这个地址中的内容被我们拿到了,我们可能就不知道这个值是合法还是非法的。建议初始化所有的指针,不知道指针应该指向什么的话,就让指针指向
nullptr
或者0
。 -
复杂的指针或者引用的声明语句,从右往左读。
-
常量引用是对
const
的引用的简称。严格来说,并不存在常量引用,因为引用不是一个对象,我们没办法让引用本身恒定不变。但是因为C++中,引用绑定的对象是不能更改的,所以从这层意义上理解,所有的引用又都称得上常量。引用的对象是常量还是非常量决定了引用能进行的操作,但是影响不到引用和对象的绑定关系。 -
指向常量的指针和对常量的引用(常量引用),可以使用非常量对象初始化指向常量的指针和常量引用,不论指向或者引用的是不是常量对象,都不能通过指针或者引用修改他们引用或者指向的对象的值。因为他们认为自己指向或者引用了常量,而常量是不能修改的,所以就不能修改了。
-
常量指针即指针本身是一个常量。它的指向不能改变,但是它指向变量的值是可以改变的。
1
2
3
4int val =3;
const int &cr = val; // 对常量的引用,引用的变量不能通过cr引用改变。
cont int *ptr = &val; // 指向常量的指针,指针指向的变量不能通过ptr指针改变。
int *const p = &val; //常量指针,指针的指向不能变,指针指向变量的值可以改变。 -
顶层
const
,变量本身是一个常量。 -
底层
cosnt
,针对于复合类型如指针和引用来说的,引用的对象是一个常量(常量引用)或者指针指向的是一个常量。 -
顶层
const
和底层const
对常量的引用(常量引用)可以和常量对量绑定;
对常量的引用(常量引用)可以和非常量对量绑定;
非常量引用不可以和常量对象绑定;
非常量引用可以和非常量对象绑定;
指向常量的指针可以指向常量对象;
指向常量的指针可以指向非常量对象;
常量指针可以指向非常量对象;
常量指针不可以指向常量对象;
普通指针不可以指向常量对象;
普通指针可以指向非常量对象;
常量指针(顶层const)可以用来初始化非常量对象。
对常量的引用和指向常量的指针(底层const)不可以用来初始化非常量对象。 -
常量表达式,值不会改变并且在编译时值就已经确定的表达式。
-
constexpr`用于声明常量表达式,常量表达式一定是常量,但是常量不一定是常量表达式。比如:
1
const int sz = get_size() //sz是常量,但是不是常量表达式
-
auto
会忽略顶层const
,保留底层const
。 -
auto
也会忽略引用。 -
设置类型为
auto
的引用,可以保留顶层const
-
decltype
的结果可以是引用,引用从来都是作为它所指对象的同义词出现,只有在decltype
处是例外。 -
如果表达式的内容是解引用操作,使用
decltype
将会得到引用类型。 -
decltype((variable))
的结果永远是引用,而decltype(variable)
的结果只有在真的是引用的时候才会返回引用。
第三章
cin
和getline
的区别,对于空白符的处理string
的初始化方式,默认初始化,拷贝初始化,直接初始化- range for语句逐字符操作。
第七章
- 构造函数。每个类都会定义它的对象被初始化的方式,类通过一个或者几个特殊的成员函数控制每个类的初始化过程,这些函数叫做构造函数。
- 前向声明。仅仅声明类而暂时不定义它,这种声明有时候也叫前向声明。
- 不完全类型。在类声明之后定义之前,这个类属于不完全类型。我们知道它是一个类,但是不清楚它到底包含哪些类型。
参考文献
1.《C++ Prime第五版》