《C++Primer 5e》学习笔记(1):变量和基本类型

1.类型转换:

(1)当我们赋给无符号类型一个超出它表示范围的值时,结果是初始值对无符号类型表示数值总数取模后的余数。例如,8比特大小的unsigned char 可以表示0到255区间内的值,如果我们赋了270,结果就是270%256=14.

(2)当我们赋给带符号类型一个超出它表示范围的值时,结果是未定义的(undefined)

2.初始化不是复制,初始化的含义是创建变量时赋予一个初始值,而赋值的含义是把对象的当前值擦除,而以一个新值来替代。

3.定义于函数体内的内置类型的对象如果没有初始化,其值是未定义的。类的对象如果没有显式的初始化,其值由类决定。

4.一个文件想要使用别处定义的名字需要用关键字extern对那个名字进行声明。变量的定义必须出现且只能出现在一个文件中。其他文件不能重复定义。

5.作用域操作符(::)可以覆盖默认的作用域:::val //使用全局变量val

6.引用必须被初始化,且只能绑定在对象上,不能与字面值或某个表达式绑定在一起。由于引用不是对象,没有实际地址,故不能定义指向引用的指针。一旦定义了引用,就无法令其再绑定到另外的对象。

int i=42,j=60;
int &r1=i; //r=42
r1=9; //正确,相当于i=9
r1=j; //正确,复制语句
&r1=j; //错误,引用不能再绑定到其他对象

7.试图拷贝或以其他方式访问无效指针的值将引发错误,编译器并不负责检查此类错误,故程序在运行期间会崩溃。

8.赋值永远改变的是"="左边的对象。一个变量的类型由左到右看,离变量名最近的符号对变量的类型有最直接的影响。

9.void *指针可以存放任意对象的地址,但不能直接操作void *指针所指的对象。

10.指针的引用:

int i=42;
int *p;
int *&r=p; //r是一个对指针p的引用
r=&i; //对r赋值,相当于p=&i
*r=6; //解引用r得到i,也就是p所指的对象,将i置为6


11.const int修饰的常量和普通的int一样都能参与算术运算,也都能转换为一个布尔值。

12.当以编译初始化的方式定义一个const类型的对象时,编译器将在编译的过程中把用到该变量的地方都替换成对应的值。默认情况下,const对象仅在文件内有效。当多个文件中出现了同名的const变量时,其实就等于在不同的文件中分别定义了独立的变量。

13.可以把引用绑定到常量上,与普通引用不同的是,对常量的引用不能被用作修改它所绑定的对象:

//"引用常量"才能引用"常量",但"引用常量"也可以引用"非常量"
int i=42;
const int i1=90;
const int &r=i;
i++; //r=43
r=90; //错误,引用常量的值不能修改
const int &r1=i1;
r1=88; //错误
int &r2=i1; //错误:试图让一个非常量引用指向一个常量对象


14.引用的类型必须与其所引用对象的类型一样,但有以下例外:初始化常量引用时允许用任意表达式作为初始值,只要该表达式的结果能转换成引用的类型即可。尤其,允许为一个常量引用绑定非常量的对象,字面值,甚至是个一般表达式。

int i=42;
const int &r1=i; //正确
const int &r2=42; //正确,r2是一个常量引用
const int &r3=r1*2 //正确,r3是一个常量引用
int &r4=r1*2; //错误,r4是一个非常量引用


15.常量引用仅对引用可参与的操作做出了限定,对于引用的对象本身是不是一个常量未做限定。因此对象可以是个非常量,允许通过其他途径来改变它的值。

int i=42;
int &r1=i; //r1绑定对象i
const int &r2=i; //r2也绑定对象i,但不允许通过r2来修改i的值
r1=6; //正确
r2=6; //错误:r2是一个常量引用,只能引用,不能修改


16.指向常量的指针不能用于改变其所指对象的值(但可以改变指针所指的对象,见下17),想要存放常量对象的地址,只能用指向常量的地址。

const double pi=3.14;
double *p=pi //错误,p是一个普通指针
const double *cp=pi //正确
*cp=4.2; //错误,不能给*cp赋值


17.指针的类型必须与其所指对象的类型一致,但有以下例外:允许一个指向常量的指针指向一个一个非常量对象:

//接上个代码
double d=1.23;
cp=&d; //正确,但不能通过cp改变d的值


和常量引用一样,指向常量的指针也没有规定其所指的对象必须是一个常量。所谓的指向常量的指针仅仅要求不能通过该指针改变对象的值,而没有规定那个对象的值不能通过其他途径改变。

18.常量指针:指针是对象而引用不是,因此就允许把指针本身定义为常量。在关键字const之间加上*说明指针本身一个常量,而非指向的那个值。

int i=42,j=90;
int *const p=&i; //p将一直指向i
*p=30; //*p=i=30
i=50; //*p=i=50
p=&j; //错误,p为常量指针,指向不能改变

const double pi=3.14;
const int *const cp=π //cp是一个指向常量的常量指针
*cp=1.23; //错误



19.顶层const和底层const

顶层const表示指针本身是个常量,用底层const表示指针所指的对象是一个常量。

更一般的,顶层const可以表示任意的对象是常量,这一点对任何数据类型都适用,如算术类型、类、指针等。底层const则与指针和引用等   复合类型的基本类型部分 有关。比较特殊的是,指针类型既可以是顶层const,也可以是底层const。

20.当执行对象的拷贝操作时,拷入和拷出的对象必须具有相同的底层const资格,或者两个对象的数据类型必须能够相互转换。一般的,非常量可以转换为常量,反之则不行。

int i=0;
int *const p1=&i; //不能改变p1的值,这是一个顶层const
const int ci=42; //不能改变ci的值,这是一个顶层const
const int *p2=&ci; //允许改变p2的值,这是一个底层const
const int *const p3=p2; //第一个是底层const,第二个是顶层const
const int &r=ci; //用于声明引用的const都是底层const
i=ci; //正确:ci是一个顶层const,对此操作无影响
p2=p3; //正确:p2和p3指向的对象类型相同,p3顶层const的部分不受影响

int *p=p3; //错误:p3包含底层const含义,而p没有
p2=p3; //正确:p2和p3都是底层const
p2=&i; //正确:int*能转换成const int*
int &r=ci; //错误:普通的int&不能绑定到int常量上
const int &r2=i; //正确:const int&可以绑定到一个普通的int上





猜你喜欢

转载自blog.csdn.net/AC_Gibson/article/details/50387429