最近在读《C++primer》英文第五版,将一些重要内容记了了下来,有的地方可能理解的不到位,希望大家可以给予指正!
Chapter2,Section2.3——Compound Types
复合类型
复合类型是根据其它类型定义出来的类型。
C++包含许多的复合类型,其中有“引用”和“指针”。
(一)引用
新标准中定义了一种引用“右值引用”,这些引用主要是使用内部类。从技术上讲,我们所说的引用都是”左值引用“。
一个引用为一个对象定义了一种可选择的名字。我们通过“&”符号来表示引用。
当定义一个引用时,我们就将这个引用与对这个引用进行初始化的对象绑定在了一起。不能将已经绑定过的引用再去绑定另一个对象。因为没有方法去重新绑定一个引用,引用必须在定义时进行初始化。
”引用就是一个别名“
一个引用并不是一个对象,一个引用仅仅是一个已经存在的对象的别名。当定义了一个引用之后,这个引用所能进行的操作和它所绑定的对象能进行的操作是相同的。
当我们给一个引用赋值时,我们相当于给该引用所绑定的对象赋值。
当我们取来一个引用的值时,我们真正取来的是该引用所绑定的对象的值。
当我们用引用去初始化其它变量时,我们真正使用的是该引用所绑定的对象去进行初始化。
因为引用不是对象,我们不能定义引用的引用。
”定义引用“
引用:类型名 &标识符。
引用和其绑定的对象的类型必须相同。(有两个例外)
一个引用可能只与对象进行绑定,不能与literal或是一般的表达式绑定。
(二)指针
指针是一种能够“指向”其他对象的复合类型,是间接操作其他对象的一种方式。
和引用的区别:
(1)一个指针在其生存周期内可以指向多个不同的对象。
(2)指针在定义时可以不进行初始化。
(3)和其他内置类型一样,如果在块定义域内为进行初始化,其值是undefined。
指针存储的是其他对象的地址,可以用&符号获得其他对象的地址。由于引用并不是一个对象,所以它没有地址。因此也就不能定义指向引用的指针。
指针和它所指向的对象的类型必须相同。(有两个例外)
"指针的值"
指针的值可以是下面四种情况中的一种:
(1)它能指向一个对象。
(2)它能指向一个对象的末尾位置。(类似容器中最后一个元素的下一个位置。)
(3)它可以是空指针,代表着它并不指向任何对象。
(4)它可以是无效的,除了前三种情况都是无效的。(类似野指针?)
(野指针:用new分配一块空间并赋给某个指针,但是这块空间后来被delete回收了之后该指针并没有指向NULL,则该指针就是野指针。)
当使用无效的指针时会发生不确定的结果,所以我们要时刻确定一个指针是否是有效的。
当我们使用(2)和(3)情况下的指针时,尽管它们是有效的,但是它们并不指向任何对象,使用它们会产生undefined结果。
”通过使用指针去使用一个对象“
当一个指针指向一个对象时,我们可以通过*运算符(解引用)去使用它所使用的对象。
只有当指针有效时,才能对它进行“解引用”操纵(*)。
”空指针“
空指针不指向任何对象。
获得空指针的方法:
(1) int *p1 = nullptr; //与int *p1 = 0;等价
(2) int *p2 = 0; //直接用literal 常量 0 进行赋值
(3) int *p3 = NULL; //与int *p3 = 0;等价
nullptr:最直接的方法。它是一个能转换成任何指针类型的literal。
NULL:预处理程序变量。头文件:cstdlib
预处理程序是在编译之前执行的,预处理程序变量直接被预处理器管理并且它也不是std命名空间中的,所以可以不用加前缀std::,而直接写他们的名字。
当我们使用预处理程序变量时,预处理器自动用它的值替代了这个变量,今后,将一个指针初始化为NULL与给它初始化成0是等价的。现代的C++应该用nullptr来替代NULL。
使用未初始化的指针常导致run-time错误。
在大多数的编译器下,当我们使用一个未初始化的指针时,内存里指针存储的位被用来当做地址,使用一个未初始化的指针就是在假定的位置请求去访问一个假定的对象。而通常无法判断在内存中为指针分配的地址十否是有效的,所以就可能导致错误的产生。
最好在要指向的对象定义之后就定义一个指针。如果指针不指向任何对象,就把它初始化成nullptr或是0。
”指针的赋值“
对于指针的赋值,并不能直接确定是改变了这个指针还是指针所指向的那个对象。要记住的是赋值改变了它的左操作数。
”其他的指针操作“
(1)条件判断。如果指针是0(不指向任何对象),条件是false。任何非0的指针都是true。
(2)有着相同类型的两个有效的指针可以进行比较操作(==,!=),结果是bool类型。当两个指针存储的地址相同时结果是true。当两个指针都是空指针、都指向同一个对象、都指向同一个对象的末尾时这两个指针是相等的。
注意:一个指向某一个对象的指针和另一个指向另一个对象末尾的指针可能有相同的地址,它们比较时是相等的。
当在条件或是比较中使用指针时,指针必须是有效的。如果使用一个无效的指针,会导致undefined结果。
“void* 指针”
void* 类型的指针可以存储任何类型对象的地址,但是在那个地址下的对象的类型是未知的。
通常我们可以将void* 类型指针与其它类型的指针作比较,我们能传递它或是在一个函数中返回它。我们不能使用它进行操作其地址下的对象,因为不知道其地址下对象的类型。
通常我们使用void* 来像内存那样来处理内存,而不是对存储在那块内存上的对象来进行操作。
(三)复合类型的声明
一个单行的定义可能定义许多不同类型的变量。
”定义多种类型的变量“
(1)单行定义。(2)多行定义。
int* p,p1;//p是指针类型,p1是int类型。*修饰p。
”指向指针的指针“
将一个指针的地址存在另一个指针里。符号:**
“绑定指针的引用”
例:int *p; int *&r = p;从右向左读。