C++ Primer阅读笔记一

类型

算数类型

类型 含义 最小尺寸
bool 布尔类型 未定义
char 字符 8位
wchar_t 宽字符 16位
char16_t Unicode字符 16位
char32_t Unicode字符 32位
short 短整型 16位
int 整型 16位
long 长整型 32位
long long 长整型 64位
float 单精度浮点数 6位有效数字
double 双精度浮点数 10位有效数字
long double 扩展精度浮点数 10位有效数字
内置类型的机器实现

计算机以比特序列存储数据,每个比特非0即1。大多数计算机以2的整数次幂个比特为块来处理内存,可寻址的最小内存块称为“字节(byte)”。存储的基本单元称为“字(word)”,它通常由几个字节组成。

除去布尔和扩展的字符外,其他整型可以划分为带符号的(signed)无符号的(unsigned)两种。带符号的类型可以表示整数、负数或0,无符号类型则仅能表示大于等于0的值。

类型转换

当从无符号数中减去一个值时,不管这个值是不是无符号数,我们都必须确保结果不能是一个负值。

1
2
3
// 错误:变量u永远也不会小于0,循环条件一直成立
for (unsigned u = 10; u >= 0; --u)
std::cout << u << std::endl;

字面值常量

转义序列

有两类程序员不能直接使用:一类是不可打印(nonprintable)的字符,如退格活其他控制字符,因为它们没有可视的图符;另一类是C++语言中有特殊含义的字符(单引号、双引号、问号、反斜线)。在这些情况下需要用到转义序列(escape sequence),转义序列均以反斜线作为开始,C++语言规定的转义序列包括:

换行符 \n 横向制表符\t 报警符\a 纵向制表符\v 退格符\b 双引号 \” 反斜线 \ 问号 \? 单引号 \’ 回车符 \r 进纸符\f

变量

变量提供一个具名的、可供程序操作的存储空间。

变量定义

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

变量声明和定义的关系

为了支持分离式编译,C++语言将声明和定义区分开来。声明(declaration)使得名字为程序所知,一个文件如果想使用别处定义的名字则必须包含对那个名字的声明。而定义(definition)负责创建与名字关联的实体。

变量能且只能被定义一次,但是可以被多次声明。

标识符

变量命名规范

  • 标识符要能体现实际含义。
  • 变量名一般用小写字母,如index。
  • 用户自定义的类名一般以大写字母开头,如Sales_item。
  • 如果标识符由多个单词组成,则单词间应该应有明显区分。

名字的作用域

复合类型

复合类型(compound type)是指基于其他类型定义的类型。

引用

引用(reference)为对象起了另外一个名字,引用类型引用另外一种类型。(引用类型的初始值必须是一个对象)

引用必须初始化。

引用并非对象,相反的,它只是为一个已经存在的对象所起的另外一个名字。

指针

指针(pointer)是“指向(point to)”另外一种类型的复合类型。与引用类似,指针也实现了对其他对象的间接访问。然而指针与引用相比又有很多不同点。其一,指针本身就是一个对象,允许对指针赋值和拷贝,而且在指针的生命周期内它可以先后指向几个不同的对象。其二,指针无需在定义时赋值。

定义指针类型的方法将声明符写成*d的形式,其中d是变量名。

引用不是对象,没有实际地址,所以不能定义指向引用的指针。

指针值

  1. 指向一个对象。
  2. 指向紧邻对象所占空间的下一个位置。
  3. 空指针。
  4. 无效指针,也就是上述情况之外的其他值。

取地址符(操作符&)

解引用符(操作符*)

如果指针指向了一个对象,则允许使用解引用符(操作符*)来访问该对象。

建议:初始化所有指针。

指向指针的指针
指向指针的引用

const界定符

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

默认状态下,const对象仅在文件内有效

如果想在多个文件之间共享const对象,必须在变量的定义之前添加extern关键字。

const的引用

可以把引用绑定到const对象上,就像绑定到了其他对象上一样,我们称之为对常量的引用(reference to const)。与普通引用不同的是,对常量的引用不能被用作修改它所绑定的对象。

指针和const

与引用一样,也可以令指针指向变量或非变量。类似于常量引用,指向常量的指针(pointer to const)不能用于改变其所指对象的值。要想存放常量对象的地址,只能使用指向常量的指针。

处理类型

类型别名

类型别名(type alias)是一个名字,它是某种类型的同义词。使用类型别名有很多好处,它让复杂的类型名字变得简单明了、易于理解和使用,还有助于程序员清楚地知道使用该类型的真实目的。

有两种方法可用于定义类型别名。传统的方法是使用关键字typedef

1
typedef double wages;

新标准规定了一种新的方法,使用别名生命(alias declaration)来定义类型的别名:

1
using SI = Sales_item; // SI是Sales_item的同义词
auto类型说明符

C++11新标准引入了auto类型说明符,用它就能让编译器替我们去分析表达式所属的类型。

decltype类型指示

C++11新标准引入了第二种类型说明符decltype,它的作用是选择并返回操作数的数据类型。在此过程中,编译器分析表达式并得到它的类型,却不实际计算表达式的值。

Q

What is the difference between ++i and i++?

++i 等价于i=i+1。递增运算将运算对象的值增加1.

1
2
3
i = 1;
j = ++i;
(i is 2, j is 2)

i++ 同样会自增i,但是返回的是原来的值。

1
2
3
i = 1;
j = i++;
(i is 2, j is 1)
1
2
3
4
5
6
7
8
9
10
11
12
13
// 前缀形式:
int& int::operator++() //这里返回的是一个引用形式,就是说函数返回值也可以作为一个左值使用
{//函数本身无参,意味着是在自身空间内增加1的
*this += 1; // 增加
return *this; // 取回值
}
//后缀形式:
const int int::operator++(int) //函数返回值是一个非左值型的,与前缀形式的差别所在。
{//函数带参,说明有另外的空间开辟
int oldValue = *this; // 取回值
++(*this); // 增加
return oldValue; // 返回被取回的值
}

###

Reference

C++ Primer第五版

https://www.zhihu.com/question/19811087

More than your eyes can see