Primer(第四版)学习笔记
- 格式:docx
- 大小:32.10 KB
- 文档页数:8
在字符 中使用单引号、反斜杠时 要使用转义字符;
在字符串中使用双引号、反斜杠时 要使用转义字符;
\?可以不必使用转义字符,直接使用?即可;
C++ 语言从 C 语言中继承下来的预处理器变量 NULL,该变量在 cstdlib头文件中定义,
其值为 0。如果在代码中使用了这个预处理器变量, 则编译时会自动被数值 0 替换。
·大多数编译器,包括那些来自 IDE 的,都提供了命令行界面。除非你已经
很熟悉你的 IDE, 否则从使用简单的命令行界面开始可能更容易些。 这样可以避
免在学习语言之前得先去学习 IDE。
表示整数、字符和布尔值的算术类型合称为整型。bool 类型表示真值 true 和
false。可以将算术类型的任何值赋给 bool 对象。0 值算术类型代表 false,任何非 0 的值都代表 true。 除 bool 类型外,整型可以是带符号的(signed) 也可以是无符号的(unsigned)。整型 int、 short 和 long 都默认为带符号型。 要获得无符号型则必须指定该类型为 unsigned,比如 unsigned long。unsigned int
类型可以简写为 unsigned,也就是说,unsigned 后不加其他类型说明符意味着是 unsigned int 。
1定义变量、指针最好在要使用之前定义,定义紧跟着使用,可读性强,也安全。
2定义变量、指针最好定义时就初始化,除非确定之后就要初始化,养成好习惯。
3如果必须分开定义指针和其所指向的对象,则将指针初始化为 0。因为编译器可检测出 0 值的指针,程序可判断该指针并未指向一个对象。
对于内置类型的初始化:当为全局变量或静态变量时,没进行初始化的话,系统自行初始化为0;当为局部变量时,系统也不进行初始化,使用则出错。
在数组中时,也同理。但是,假如仅初始化了其中的一个元素,则系统会自动初始化之后的元素,如:int型仅初始化第一个,之后的系统默认初始化为0;char型仅初始化第一个元素,之后的系统默认初始化为 '\0'
对于类类型的初始化:无论是全局变量还是局部变量,米有进行初始化的话,其都将调用自己定义时的默认构造函数(不是构造函数)。如果没有定义默认构造函数的话,必须手动初始化,或必须有初始化的成员函数。
如:string类型的默认构造函数即为初始化为空的字符串。
像 42 这样的值, 在程序中被当作字面值常量。 称之为字面值是因为只能用
它的值称呼它, 称之为常量是因为它的值不能修改。每个字面值都有相应的类型,例如:0 是 int 型,3.14159 是 double 型。只有内置类型存在字面值,没有类类型的字面值。因此,也没有任何标准库类型的字面值。
两个相邻的仅由空格、 制表符或换行符分开的字符串字面值(或宽字符串字
面值), 可连接成一个新字符串字面值。 这使得多行书写长字符串字面值变得简单: // concatenated long string literal
std::cout << "a multi-line " "string literal "
"using concatenation"
除了关键字, C++ 标准还保留了一组标识符用于标准库。 标识符不能包含两
个连续的下划线, 也不能以下划线开头后面紧跟一个大写字母。 有些标识符(在
函数外定义的标识符)不能以下划线开头。
内置类型变量是否自动初始化取决于变量定义的位置。 在函数体外定义的变量都初始化成 0, 在函数体里定义的内置类型变量不进行自动初始化。 除了用作赋值操作符的左操作数, 未初始化变量用作任何其他用途都是没有定义的。 未初始化变量引起的错误难于发现。正如我们在第 2.2 节劝告的, 永远不要依赖未定义行为。 即使是静态变量。。。。建议每个内置类型的对象都要初始化。
虽然这样做并不总是必需的, 但是会更加容易和安全, 除非你确定忽略
初始化式不会带来风险。
const定义方式时必须初始化:
const限定符提供了一个解决办法,它把一个对象转换成一个常量。
因为常量在定义后就不能被修改,所以定义时必须初始化,可以初始化为字面值常量,或整型表达式,或变量。
const int i, j = 0; // error: i is uninitialized const
而static静态局部变量仅能初始化一次。
全局变量有static型,extern型两种;前置必须显式定义出来,后者不必显式定义,没注明的情况下即extern型的全局变量。static型仅在本文件可见,全程序不可见,extern型在全程序都可见,只是在外部文件得extern声明一下。
const 修饰的全局变量,除了不能修改外,仅能在本文件可见;
extern const修饰的全局变量,不能被修改,在全程序都可见,但是需要extern
const来声明一下。
引用定义时必须初始化;
非const引用应初始化为同类型变量名,不能赋字面值,初始化完后才可以赋字面值;
int ival = 1024;
int &refVal = ival; // ok: refVal refers to ival
int &refVal2; // error: a reference must be initialized
int &refVal3 = 10; // error: initializer must be an object
const引用却可以初始化为字面值,甚至初始化为任何类型的变量名,但它不能改变与其相关联的变量:
const int &r = 42;
double dval = 3.14;
const int &ri = dval; //这时修改ri不会影响到dval
本例中, 枚举成员 point2d 显式初始化为 2。 下一个枚举成员 point2w 默认初始化,即它的值比前一枚举成员的值大 1。因此 point2w 初始化为 3。枚举成员 point3d 显式初始化为 3。一样,point3w 默认初始化,结果为 4。 不能改变枚举成员的值。 枚举成员本身就是一个常量表达式, 所以也可用于需要常量表达式的任何地方。
枚举类型的对象的初始化或赋值,只能通过其枚举成员或同一枚举类型的其他对象来进行。初始化或幅值完后,使用的时候相当于整数一样。打印枚举变量时也显示整数。
定义变量和定义数据成员存在非常重要的区别: 一般不能把类成员的初始化
作为其定义的一部分。当定义数据成员时,只能指定该数据成员的名字和类型。
类不是在类定义里定义数据成员时初始化数据成员,而是通过称为构造函数
用 class 和 struct 关键字定义类的唯一差别在于默认访问级别:
默认情况下, struct 的成员为 public, 而 class 的成员为 private
定义仅可以出现一次,声明可以出现多次:
设计头文件的时候要谨遵这一点,因为头文件可能被同一个程序中多个源文件引用,导致多重定义 而链接错误,这种定义只能在源文件中出现。所以头文件中只能进行声明,不能进行定义,除了:1.定义类 2. 定义inline内联函数 3.
定义const对象(需初始化为常量表达式,否则也不能在头文件中定义)
设计头文件时, 应使其可以多次包含在同一源文件中, 这一点很重要。我们必须保证多次包含同一头文件不会引起该头文件定义的类和对象被多次定义。 使得头文件安全的通用做法, 是使用预处理器定义头文件保护符。 头文件保护符用于避免在已经见到头文件的情况下重新处理该头文件的内容。
#ifndefine #define #endif
头文件应该含有保护符, 即使这些头文件不会被其他头文件包含,或仅被包含1次。编写头文件保护符并不困难, 而且如果头文件被包含多次,它可以避免难以理解的编译错误。
结语:1.因为头文件可能被多个源文件包含,所以头文件不能进行定义,只能进行声明【否则就会导致多重定义,链接错误】,除了(初始化为整形表达式的const变量、内联函数、类可以被定义)。
2.因为头文件可能被多次包含在同一源文件中,所以要使用预处理器定义文件保护头,来避免在同一源文件中的多重定义错误。
:: 该操作符是作用域操作符。 它的含义是右操作数的名字可以在左操作数的作用域中找到。因此,std::cin 的意思是说所需要名字 cin 是在命名空间 std 中定义的。
一般情况下都使用命名空间的using机制,但有一种情况下,必须总是使用完全限定的标准库名字:在头文件中。理由是头文件的内容会被预处理器复制到程序中。用 #include 包含文件时,相当于头文件中的文本将成为我们编写的文件的一部分。如果在头文件中放置 using 声明,就相当于在包含该头文件 using 的每个程序中都放置了同一 using,不论该程序是否需要 using 声明(假如不需要的话,可能文件中会出现变量的重定义错误)。 sentinel(哨兵) 一种程序设计技术,使用一个值来控制处理过程。在本章中使用由 end( )操作返回的迭代器作为保护符,当处理完 vector 对象中的所有元素后,用它来停止处理 vector 中的元素。其它的比如数组中利用数组总数作为哨兵来停止操作。
现代 C++ 程序应尽量使用 vector 和迭代器类型,而避免使用低级的数组和指针。设计良好的程序只有在强调速度时才在类实现的内部使用数组和指针。
与 vector 类型相比, 数组的显著缺陷在于: 数组的长度是固定的, 而且程
序员无法知道一个给定数组的长度。 数组没有获取其容量大小的 size 操作, 也
不提供 push_back 操作在其中自动添加元素。如果需要更改数组的长度,程序
员只能创建一个更大的新数组,然后把原数组的所有元素复制到新数组空间中
去。 与使用标准 vector 类型的程序相比,依赖于内置数组的程序更容易出错而且难于调试。在出现标准库之前,C++ 程序大量使用数组保存一组对象。 而现代的 C++ 程序则更多地使用 vector 来取代数组, 数组被严格限制于程序内部使用, 只有当性能测试表明使用 vector 无法达到必要的速度要求时, 才使用数组。 然而, 在将来一段时间之内, 原来依赖于数组的程序仍大量存在, 因此, C++ 程序员还是必须掌握数组的使用方法。
数组的维数必须用值大于等于 1 的常量表达式定义。此常量表达式只能包含整型字面值常量、枚举常量或者用常量表达式初始化的整型 const 对象。 非 const
变量以及要到运行阶段才知道其值的 const变量都不能用于定义数组的维数。动态分配内存空间函数new时,其下标操作符[ ]中可以是任意表达式。
容器中有其固有的索引类型size_type、difference_type,来操作下标和下标间距。数组中操作下标时可以定义size_t、ptrdiff_t类型进行操作。这比较规范点!
与 vector 不同,一个数组不能用另外一个数组初始化,也不能将一个数组赋值给另一个数组 。