第二章 变量和基本类型

来源:互联网 发布:燕十八php教程垃圾 编辑:程序博客网 时间:2024/06/05 06:11
  1. C++语言规定:一个int至少和一个short一样大,一个long至少和一个int一样大,一个long long至少和一个long一样大。
  2. 可寻址的最小内存块成为“字节(byte),存储的基本单元称为“字(word)”。字由32或64比特构成。
  3. 和C语言一样,C++的设计准则之一也是尽可能地接近硬件。
  4. 当明确知晓数值不可能为负时,选用无符号类型。
  5. 使用int执行整数运算。在实际应用中,short常常显得太小而long一般和int有一样的尺寸。如果你的数值超过了int的表示范围,选用long long。
  6. 在算数表达式中不要使用char和bool,只有在存放字符或布尔值时才使用它们。因为类型char在一些机器上是有符号的,而在另一些机器上又是无符号的,所以如果使用char进行运算特别容易出问题。如果你需要使用一个不大的整数,那么明确指定它的类型是signed char或者unsigned char。
  7. 执行浮点数运算选用double,这是因为float通常精度不够而且双精度浮点数和单精度浮点数的计算代价相差无几。事实上,对于某些机器来说,双精度运算甚至比单精度浮点数的计算还快。long double提供的精度在一般情况下是没有必要的,况且它带来的运算时消耗也不容忽视。
  8. 当我们把一个整数值赋给浮点类型时,小数部分记为0。如果该整数所占的空间超过了浮点类型的容量,精度可能丢失。
  9. 当我们赋给无符号类型一个超出它的表示范围的值时,结果是初始值对无符号类型表示数值总数取模后的余数。(求模运算与求余运算的区别)
  10. 当我们赋给带符号类型一个超出它表示范围的值时,结果是未定义的(undefined)。此时,程序可能继续工作、可能崩溃,也可能生成垃圾数据。
  11. 建议:避免无法预知和依赖于实现环境的行为。(如果我们把int的尺寸看成是一个确定不变的已知值,那么这样的程序就称作不可移植的(non-portable)。)
  12. //错误:变量u永远也不会小于0,循环条件一直成立for (unsigned u = 10; u >= 0; --u)        std::cout << u << std::endl;
  13. 以0开头的整数代表八进制数,以0x或0X开头的代表十六进制数。(20/*十进制数*/   024/*八进制数*/    0x14/*十六进制数*/)
  14. 默认情况下,十进制字面值是带符号数的,八进制和十六进制字面值可能是带符号的也可能是无符号的。十进制字面值的类型是int、long、long long中能容纳当前值的尺寸最小的那个。 八进制和十六进制字面值的类型是能容纳其数值的int、unsigned int、long、unsigned long、long long、unsigned long long中尺寸最小者。如果一个字面值连与之关联的最大的数据类型都放不下,将产生错误。
  15. 类型short没有对应的字面值。
  16. 十进制字面值不会是负数。如果我们使用了一个形如-42的负十进制字面值,那个负号并不在字面值之内,它的作用仅仅是对字面值取负值而已。
  17. 默认的,浮点型字面值是一个double。
  18. 编译器在每个字符串的结尾处添加一个空字符('\0')。
  19. 当书写的字符串字面值比较长,卸载一行里不太合适时,就可以采取分开书写的方式:
    //分多行书写的字符串字面值std::cout << "a really, really long string literal "                    "that spans two lines" << std::endl;
  20. utf-8,用8位编码一个Unicode字符。
  21. u'a';                 //Unicode16字符型字面值,类型是char16_tU'a';                 //Unicode32字符型字面值,类型是char32_tL'a';                 //宽字符型字面值,类型是wchar_tu8"hi!";              //utf-8字符串字面值42l;                  //long42L;                  //long42ll;                 //long long42LL;                 //long long42ull;                //unsigned long long3.14f;                //float3.14F;                //float3.14l;                //long double3.14L;                //long double
  22. 当使用一个长整型字符串字面值时,请使用大写字母L来标记,因为小写字母l和数字1太容易混淆了。
  23. '\012'=='\12'
  24. C++程序员们在很多场合都会使用对象(object)这个名词。通常情况下,对象是指一块能存储数据并具有某种类型的内存空间。
  25. 初始化不是赋值,初始化的含义是创建变量时赋予其一个初始值,而赋值的含义是把对象的当前值擦出,而以一个新值来替代。
  26. //以下的4条语句都可以初始化变量int units_sold = 0;int units_sold = {0};    //列表初始化int units_sold{0};       //列表初始化int units_sold(0);
  27. 作为C++11新标准的一部分,用花括号来初始化变量得到了全面应用,在此之前,这种初始化的形式仅在某些受限场合下才能使用。当用于内置类型的变量时,这种初始化有一个重要特点:如果我们使用列表初始化且初始值存在丢失信息的风险,则编译器会报错;例如:
    long double ld = 301415926536;int a{ld}, b = {ld};      //错误:转换未执行,因为存在丢失信息的危险int a(ld), b = (ld);      //正确:转换执行,且确实丢失了部分值
  28. 如果定义变量时没有指定初值,则变量被默认初始化(default initialized),此时变量被赋予了“默认值”。如果是内置类型的变量为被显示初始化,它的值由定义的位置决定,定义于任何函数体之外的变量被初始化为0,而定义在函数体内部的内置类型变量将不被初始化(uninitialized)。
  29. 建议初始化每一个内置类型的变量。虽然并非必须这么做,但如果我们不能确保初始化后程序安全,那么这么做不失为一种简单可靠的方法。
  30. C++语言支持分离式编译(separate compilation),该机制允许将程序分割为若干个文件,每个文件可被独立编译。
  31. 声明(declaration)使得名字为程序所知,一个文件如果想使用别处定义的名字则必须包含对那个名字的声明。定义(definition)负责创建与名字关联的实体。例如:
    extern int i;          //声明i而非定义iint j;                 //声明并定义jextern int z = 1;      //定义。但会引发错误,因为变量能且只能被定义一次,但是可以被多次声明。
  32. C++是一种静态类型(statically typed)语言,其含义是在编译阶段检查类型。其中,检查类型的过程称为类型检查(type checking)。
  33. C++的标识符(identifier)由字母、数字和下划线组成,其中必须以字母或下划线开头。标识符的长度没有限制,但是对大小写字母敏感。
  34. 标识符要能体现实际含义。
  35. 变量名一般用小写字母,如index,不要使用Index或INDEX。
  36. 用户自定义的类名一般以大写字母开头,如Sales_item
  37. 如果标识符由多个单词组成,则单词间应有明显区分,如student_loan或studentLoan,不要使用studentloan。
  38. 一般来说,在对象第一次被使用的地方附近定义它是一种好的选择,因为这样做有助于更容易地找到变量的定义。更重要的是,当变量的定义与它的第一次被使用的地方很近时,我们也会赋给它一个比较合理的初始值。
  39. 复合类型(compound type)是指给予其他类型定义的类型。例如引用和指针。
  40. 当我们使用术语“引用(reference)”时,指的是“左值引用(lvalue reference)”。
  41. 引用为对象起了另外一个名字,引用类型引用另外一种类型。例如:
    int ival = 1024;int &refVal = ival;      //refVal指向ival(是ival的另外一个名字)int &refVla2;            //错误:引用必须被初始化
  42. 一旦初始化完成,引用将和它的初始值对象一直绑定在一起,因此无法令引用重新绑定到另外一个对象,因此引用必须初始化。
  43. 引用并非对象,相反的,它只是为一个已经存在的对象所起的另外一个名字。因为引用本身不是一个对象,所以不能定义引用的引用。
  44. 引用只能绑定在对象上,而不能与一个字面值或某个表达式的计算结果绑定在一起。
  45. 指针(pointer)是“指向(point to)”另外一种类型的符合类型。
  46. 指针与引用有很多的不同点。其一,指针本身就是一个对象,允许对指针赋值和拷贝,而且在指针的生命周期内它可以先后指向几个不同的对象;其二,指针无须在定义时赋初值。和其他类型一样,在快作用于内定义的指针如果没有被初始化,也将拥有一个不确定的值。
  47. 因为引用不是对象,没有实际地址,所以不能定义指向引用的指针。
  48. 如果指针指向了一个对象,则允许使用解引用符(操作符*)来访问该对象。
  49. 解引用才做仅适用于那些确实指向了某个对象的有效指针。
  50. 几种生成空指针的方法(在新的标准下,现在的C++程序最好使用nullptr,同时尽量避免使用NULL):
    int *p1 = nullptr;      //等价于int *p1 = 0int *p2 = 0;            //直接将p2初始化为字面常量0// 需要首先#include cstdlibint *p3 = NULL;         //等价于int *p1 = 0
  51.  建议:初始化所有指针。
  52. 只要指针拥有一个合法值,就能将它用在条件表达式中。如果指针的值是0,条件取false;否则,条件取true。
  53. 很多程序员容易迷惑于基本数据类型和类型修饰符的关系,其实后者不过是声明符的一部分罢了。
  54. int i = 42;      int *p;           // p是一个int型指针int *&r = p;      // r是一个对指针p的引用
  55. 如果想在多个文件之间共享const对象,必须在变量的定义之前添加extern关键字。
  56. double dval = 3.14;const int &r1 = dval;//此处r1引用了一个int型的数,对r1的操作应该是整数运算,但dval却是一个双精度浮点数。因此为了确保r1绑定一个整数,编译器把上述代码变成如下形式:const int temp = dval;      // 由双精度浮点数生成一个临时的整型变量const int &r1 = temp;      // 让r1绑定这个临时量
  57. 所谓指向常量的指针,仅仅要求不能通过该指针改变对象的值,而没有规定那个对象的值能不能通过其他途径改变。
  58. int errNumb = 0;int *p1 = &errNumb;const int *p2 = &errNumb;            // point to constint *const p3 = &errNumb;            // const pointconst int *const p4 = &errNumb;      // a const point that point to const
  59. 顶层const(top-level const)表示指针本身是个常量;底层const(low-level const)表示指针所指的对象是一个常量。更一般的,顶层const可以表示任意的对象是常量,这一点对任何数据类型都适用。底层const则与指针和引用等复合类型的基本类型部分有关。
  60. 常量表达式(const expression)是指值不会改变并且在编译过程中就能得到计算结果的表达式。一个对象(或表达式)是不是常量表达式由它的数据类型和初始值共同决定。
  61. C++新标准规定,允许将变量声明为constexpr类型以便由编译器来验证变量的值是否是一个常量表达式。声明为constexpr的变量一定是一个常量,而且必须用常量表达式初始化。
  62. 算术类型、引用和指针都属于字面类型。自定义类、IO库、string类则不属于字面值类型,也就不能被定义成constexpr。
  63. 在constexpr声明中如果定义了一个指针,限定符constexpr仅对指针有效,与指针所指的对象无关。
    const int *p = nullptr;    // p是一个指向整型常量的指针constexpr int *q = nullptr;    // q是一个指向整数的常量指针constexpr const int *r = nullptr;    // r是常量指针,指向整型常量
  64. pstring实际上是指向char的指针,因此,const pstring就是指向char的常量指针。
    typedef char *pstring;const pstring cstr = 0;    // cstr是指向char的常量指针const pstring *ps;         // ps是一个指针,它的对象是指向char的常量指针
  65. auto一般会忽略掉顶层const,同时底层const则会保留下来。设置一个类型为auto的引用时,初始值中的顶层常量属性仍然保留。
  66. 如果表达式的内容是解引用操作,则 decltype 将得到引用类型:
    int i = 42, *p = &i, &r = i;decltype(r + 0) b;    // 正确:加法的结果是int,因此b是一个(未初始化)的intdecltype(*p) c;       // 错误:c是int&,必须初始化
  67. 切记:decltype((variable))(注意是双层括号)的结果永远是引用,而decltype(varialbel)结果只有当variable本身就是一个引用时才是引用。
  68. 如果i是int,则表达式i = x的类型是int&,即decltype(i = x)得到的类型是引用。
  69. 从最基本的层面理解,数据结构是把一组相关的数据元素组织起来然后使用它们的策略和方法。
  70. 很多新手程序员经常忘了在类定义的最后加上分号。
  71. 头文件通常包含哪些只能被定义一次的实体,如类、const和constexpr变量等。
  72. 头文件一旦被改变,相关的源文件必须重新编译以获取更新过的声明。
  73. 当预处理器看到#include标记时就会用指定的头文件的内容代替#include。
  74. 预处理变量无视C++语言中关于作用域的规则。
0 0