首页 > 技术文章 > 学习笔记之C++ Primer中文版(第五版)

pegasus923 2017-06-23 22:34 原文

非常权威系统的语言书,正好学习下C++11内容。

 

C++ Primer_百度百科

http://baike.baidu.com/link?url=YLvDJE9w3CjGp3eQwjuXYKUZs7vTcOttzSGg-4hmf0Cnci4ncDNRlremuq_bPKyUCyJFam1whnYz3vfrQw1ILaOckUWhq5M59AqjuUBhi0O

 

第1章   快速入门
第I部分  C++基础
  • C++是一种静态数据类型语言,它的类型检查发生在编译时。
第2章   变量和基本类型
  • 当明确知晓数值不可能为负时,选用无符号类型。
  • 使用int执行整数运算。如果数值超过int的表示范围,使用long long。
  • 在算术表达式中不要使用char或bool,只有在存放字符或布尔值时才使用它们。
  • 执行浮点数运算选用double。
  • unsigned char c = -1;  // 假设char占8 bit,c的值为255
  • 当赋值给无符号类型一个超出它的范围的值时,结果是初始值对无符号类型表示数值总数取模后的余数。
  • 当赋值给带符号类型一个超出它的范围的值时,结果是未定义的。
  • 程序也应该尽量避免依赖于实现环境的行为。如果把int的尺寸看成是一个确定不变的已知值,那么这样的程序就称作不可移植的。
  • 当一个算术表达式中既有无符号数又有int值时,那个int值就会转换成无符号数。
  • 切勿混用带符号类型和无符号类型。
  • 初始化不是赋值,初始化是创建变量时赋予其一个初始值,而赋值的含义是把对象的当前值擦除,而以一个新值来替代。
  • C++11无论是初始化对象还是某些时候为对象赋新值,都可以使用一组由花括号括起来的初始值了(列表初始化)。
  • 如果我们使用列表初始化且初始值存在丢失信息的风险,则编译器会报错。
  • 定义在函数体内部的内置类型参数将不被默认初始化。
  • 如果想声明一个变量而非定义它,就在变量名前添加关键字extern,而且不要显示的初始化变量。
  • 建议:当你第一次使用变量时再定义它。
  • 引用并非对象,只是为一个已经存在的对象所起的另一个名字。所以不能定义引用的引用。
  • 引用必须初始化,而且只能绑定在对象上。
  • C++11最好用nullptr初始化指针得到空指针,同时尽量避免使用NULL。
  • 一旦定义了引用,就无法再令其绑定到另外的对象。
  • 如果你认定一个变量是常量表达式,那就把它声明成constexpr类型。
  • C++11规定了新的方法用别名声明来定义类型的别名,关键字using。
  • C++11引入了auto类型说明符。auto让编译器通过初始值来推算变量的类型。显然,auto定义的变量必须有初始值。
  • 因为一条auto的声明语句只能有一个基本数据类型,所以该语句中所有变量的初始数据类型必须一样。
  • C++11引入了第二种类型说明符decltype,它的作用是选择并返回操作数的数据类型。
  • decltype((variable)) (双层括号)的结果永远是引用,而decltype(variable)结果只有当variable本身是引用时才是引用。
  • 最好不要把对象的定义和类的定义放在一起。
  • 为了确保各个文件中类的定义一致,类通常定义在头文件中,而且类所在头文件的名字应与类的名字一样。
  • 头文件即使没有被包含在任何其他头文件中,也应该设置保护符(#define, #ifdef, #ifndef, #endif),防止重复包含的发生。

第3章  字符串、向量和数组

  •  位于头文件的代码,一般来说不应该使用using声明。这是因为头文件的内容会拷贝到所有引用它的文件中去,如果头文件里有某个using声明,那么每个使用了该头文件的文件都会有这个声明。对于某些程序来说,由于不经意间包含了一些名字,反而可能产生始料未及的名字冲突。
  • 使用=初始化变量,实际上执行的是拷贝初始化。与之相反,不使用=,则是直接初始化。
  • 如果表达式中有size()函数就不要再使用int了,这样可以避免混用int和unsigned可能带来的问题。
  • C++中字符串字面值并不是标准库类型string的对象。切记,字符串字面值与string是不同的类型。
  • cctype头文件中定义了一组标准库函数来处理string对象中的字符。
  • 如果想对string对象中的每个字符做操作,C++11最好的方法是用范围for (range for)语句。
  • size()函数返回的是一个string::size_type类型的值,这些配套类型体现了标准库类型与机器无关的特性。
  • string对象的下标必须大于等于0而小于s.size()。使用超出此范围的下标将引发不可预知的结果,以此推断,使用下标访问空string也会引发不可预知的结果。
  • vector是模版而不是类型,由它生成的类型必须包含vector中元素的类型,如vector<int>。
  • C++新标准提供了另外一种为vector对象的元素赋初始值的方法,即列表初始化。用花括号括起来的0个或多个值被赋给vector对象。
  • 范围for语句内部不应改变其所遍历序列的大小。
  • vector对象的类型总是包含着元素的类型。E.g. vector<int>::size_type。
  • vector对象及string对象的下标运算符可用于访问已存在的元素,而不能用于添加元素。
  • 只能对确知已存在的元素执行下标操作。否则buffer overflow。确认下标合法的一种有效方法就是尽可能使用范围for语句。
  • 如果容器为空,则begin和end返回的是同一个迭代器,都是尾后迭代器。
  • 因为end返回的迭代器并不实际指示某个元素,所以不能对其进行递增或解引用的操作。
  • 如果vector对象或string对象是常量,只能使用const_iterator。
  • 为了便于得到const_iterator类型的返回值,C++11引入了两个新函数cbegin()和cend()。
  • 箭头运算符(->)把解引用和成员访问两个操作结合在一起。I.e. it->mem == (*it).mem。
  • 但凡是使用了迭代器的循环体,都不要向迭代器所属的容器添加元素。
  • 数组的维度必须是一个常量表达式constexpr。
  • 在使用数组下标的时候,通常将其定义为size_t类型。这是一种机器相关的无符号类型,被设计的足够大以便能表示内存中任意对象的大小。在cstddef头文件中定义了size_t类型。
  • 内置的下标运算符所用的索引值不是无符号类型,这点与vector和string不一样。
  • 使用范围for语句处理多维数组,除了最内层的循环外,其他所有循环的控制变量都应该是引用类型。
  • end是string和vector的成员,返回一个尾后迭代器,位于容器尾元素的下一位置。也是一个标准库函数,输入一个数组,返回指向该数组尾元素的下一位置的指针。

第4章  表达式

第14章  重载运算与类型转换

  • 通常,输出运算符应该主要负责打印对象的内容而非控制格式,输出运算符不应该打印换行符。
  • 输入输出运算符必须是普通非成员函数,而不能是类的成员函数。否则,它们的左侧运算对象将是我们的类的一个对象。假设输入输出运算符是某个类的成员,则它们也必须是istream或ostream的成员。然而,这两个类属于标准库,并且我们无法给标准库中的类添加任何成员。当然,IO运算符通常需要读写类的非公有数据成员,所以IO运算符一般被声明为友元。
  • 输入运算符必须处理输入可能失败的情况,而输出运算符不需要。

推荐阅读