(2)变量和基本类型

来源:互联网 发布:手机端淘宝钻展位置 编辑:程序博客网 时间:2024/06/16 19:09

       数据类型是程序的基础;它告诉我们数据的意义以及我们能在数据上执行的操作。 C++定义了几种基本的内置类型(如字符、整型。浮点型等),本节主要讲述内置类型。

1. 与其他整型不同,字符型被分为了三种:char 、signed char 和unsigned char。特别需要注意的是:类型char和类型 signed char并不一样。尽管字符型有三种,但是字符的表现形式却只有两种:带符号和不带符号的。所以类型char实际上会表现为上述两种形式中的一种,具体是哪种由编译器决定。

2. 在类型转换中,需要记住的是:当我们赋给无符号类型一个超出它表示范围的值时,结果是初始值对无符号类型表示数值总数取模后的余数。例如:8比特大小的unsigned char 可以表示0-255区间内的值,如果我们赋予了一个区间外的值,则实际的结果是该值对256取模后所得的余数。因此,把-1赋给8比特大小的unsigned char 所得的结果是255。

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

4. 如果我们把一个布尔值用在算术表达式里,则它的取值非0即1,所以一般不宜在算术表达式里使用布尔值。

5. 把负数转换成无符号数类似于直接给无符号数赋一个负值,结果等于这个负数加上无符号数的模。

6. 如果表达式里既有带符号类型又有无符号类型,当代符号类型取值为负时会出现异常结果,这是因为带符号数会自动转换为无符号数。

7. 对于转义序列,注意:如果反斜线 \ 后面跟着的八进制数字超过3个,只有前3个数字与 \ 构成转义序列,相反\x 要用到后面跟着的所有数字。(37)

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

9. 列表初始化:作为C++11新标准的一部分,用花括号来初始化变量即列表初始化。当用于内置类型的变量时,这种初始化形式有一个重要特点:如果我们使用列表初始化且初识值存在丢失信息的风险,则编译器将报错(39):

long double id=3.141592654;

int a{id},b={id}; //错误:转换未执行,因为存在丢失信息的风险

int c(id),d=id; //正确:转换执行,且确实丢失了部分值

10. 默认初识化:定义于任何函数体之外的变量被初始化为0。定义在函数体内部的的内置变量类型变量将不被初始化。一个未被初始化的内置类型变量的值时未定义的,如果试图拷贝或以其他形式访问此类值将引发错误。类的对象如果没有显式地初识化,则其值由类确定。建议初识化每一个内置类型的变量。虽然并非必须这么做,但如果我们不能确保初始化后程序安全,那么这么做不失为一种简单可靠的方法(40)。

11. 变量声明和定义的关系:变量声明规定了变量的类型和名字,使得名字为程序所知,一个文件如果想使用别处定义的名字则必须包含对那个名字的声明。而定义负责创建名字相关的实体。如果想声明一个变量而非定义它,就在变量名前加关键字extern,而且不要显式地初始化变量:

extern int I; //声明I 而非定义I

int j; //声明并定义j

任何包含了显式初始化的声明即成为定义。因此

extern double p=3.14; //定义

同时,请注意:在函数体内部,如果试图初始化一个有 extern 关键字标记的变量,将引发错误,变量可以多次声明,但是只能被定义一次(41)。

12. 如果在多个文件中使用同一个变量,就必须将声明和定义分离。此时,变量的定义必须出现在且只能出现在一个文件中,而其他用到该变量的文件必须对其进行声明,却绝对不能重复定义(41)。

13. 标识符:C++中的标识符由字母、数字和下划线组成。其中必须以字母或下划线开头。标识符长度没有限制,但是对大小写敏感。用户自定义的标识符中不能连续出现两个下划线,也不能以下划线紧连大写字母开头。此外,定义在函数体外的标识符不能以下划线开头(43)。

14. 使用作用域操作符来覆盖默认的作用域规则。如果函数有可能用到某全局变量,则不宜定义一个同名的局部变量(44)。

15. 一旦初始化完成,引用将和它的初始值一直绑定在一起。因为无法令引用重新绑定到另外一个对象,因此引用必须初始化。引用的类型都要和与之绑定的对象严格匹配,这里有两个例外的情况:在初始化常量引用是允许用任意表达式作为初值,只要该表达式的结果能转换成引用的类型即可,尤其,允许一个常量引用绑定非常量的对象、字面值,甚至是一个一般表达式。而且,引用只能绑定在对象上,而不能与字面值或者某个表达式的计算结果绑定在一起(46)。

16. 如果在一条语句中定义几个引用/指针,每个变量前面都必须有&/*。注意:引用不是对象,没事实际地址,所以不能定义指向引用的指针(47)。

17. 试图拷贝或以其他方式访问无效指针都将引发错误(48)。

18. 生成空指针的方法(48):

   int *p1=nullptr; //C++11新标准,等价于 int *p1=0

   int *p2=0; //直接将p2初始化为字面常量0

   //首先需要 #include cstdlib

   int *p3=NULL; //等价于 Int *p3=0;

19. 注意:把int变量值直接赋给指针是错误的操作,即使Int 变量的值恰好等于0也不行。建议初识化所有指针,并且在可能的情况下,尽量等定义了对象之后再定义指向它的指针(49)。

20. 一个指针指向某对象,同事另一个指针指向另外对象的下一地址,此时也有可能出现这两个指针值相同的情况,即指针相等(50)。

21. 引用本身不是对象,因此不能定义指向引用的指针。但是指针是对象,所以存在对指针的引用(52)。

22. const对象一旦创建以后其值就不能改变,所以const对象必须初始化(53)。

23. 注意以下例子:

int i = 42;

const int ci = i; //正确:i的值被拷贝给了ci

int j = ci; //正确:ci的值被拷贝给了j

尽管 ci 是整型常量,但无论如何ci中的值还是一个整型数。Ci的常量特征仅仅在执行改变ci的操作时才会发挥作用。当用ci去初始化j 时,根本无须在意ci是不是一个常量。拷贝一个对象的值并不会改变它,一旦拷贝完成,新的对象就和原来的对象没什么关系了(53)。

24. 默认情况下,const对象被设定为仅在文件内有效。当多个文件中出现了同名的const变量时,其实等同于在不同文件中分别定义了独立的变量。只在一个文件中定义const,而在其他多个文件中声明并使用它,解决办法是,对于const变量,不管是声明还是定义都添加extern关键字,这样只需要定义一次就够了(54)。

25. 要想存放常量对象的地址,只能使用指向常量的指针。指针的类型必须与其所指向对象的类型一致,但是有两个例外:①允许令一个指向常量的指针指向一个非常量对象。所谓指向常量的指针仅仅要求不能通过该指针改变所指对象的值,而没有规定那个对象的值不能通过其他途径改变(56)。

26. 常量指针(* T const ptr)必须初始化,而且一旦初始化完成,则它的的(也就是存放在指针中的那个地址)就不能再改变了(56)。

27. 顶层const表示指针本身是个常量;而底层const表示指针所指的对象是一个常量。指针类型既可以是顶层const也可以是底层const。当执行对象的拷贝操作时,常量式顶层的还是底层的差别明显。其中,顶层const不受什么影响。另一方面,当执行对象的拷贝操作时,拷入和拷出的对象必须具有相同的底层const资格,或者两个对象的数据类型必须能够转换。一般来说,非常量可以转换成常量,反之则不行(58)。

28. 常量表达式是指值不会改变并且在编译过程就能得到计算结果的表达式。显然字面值属于常量表达式,用常量表达式初始化的const对象也是常量表达式。

const int max_files =20; //max_files是常量表达式

int staff_size = 27 ; //staff_size 不是常量表达式

const int sz = get_size( ); //sz不是常量表达式

sz尽管本身是一个常量,但是它的具体值直到运行时才能获取到,所以不是常量表达式。

29. C++11新标准规定,允许将变量声明为 constexpr 类型以便由编译器来验证变量的值是否是一个常量表达式。声明为 constexpr 的变量一个是一个常量,而且必须是用常量表达式来初始化(59)。函数体内定义的变量一般来说并非存放在固定地址中,因此constexpr指针不能指向这样的变量。相反的,定义在所有函数体之外的对象其地址不变,能用来初始化constexpr指针。必须明确一点,在constexpr声明中如果定义了一个指针,限定符constexpr仅对指针有效,与指针所指的对象无关(59)。与其他常量指针类似,constexpr指针既可以指向常量也可以指向非常量(60)。

30. 类型别名:

l typedef double wages; //wages是double的类型别名

l using wages = double; //同上

31. auto 类型说明符:在C++11标准中,用 auto能帮我们去分析表达式所属的类型,显然,auto定义的变量必须有初始值。使用auto也能在一条语句中声明多个变量,但是该语句中所有变量的初始基本数据类型都必须一样(61)。auto一般会忽略顶层const,同时底层const则会保留下来(62)。

32. decltype C++11中的新标准。作用是选择并返回操作数的数据类型。需要指出的是,引用从来都作为其所指对象的同义词出现,只有用在declype处是一个例外。需要注意的是,decltype((variable))(注意双层括号)的结果永远是引用(那么就要初始化)。而decltype(variable)结果只有当variable本身就是一个引用是才是引用(63)。

0 0
原创粉丝点击