2.1 基本内置类型
数据类型long long是在C++11中新定义的。
练习2.1:类型int、long 、 long long和short的区别是什么?无符号类型和带符号的类型的区别是什么?float和double的区别是什么?
int是整型,long是长整型。无符号类型中所有比特都用来存储值。浮点型可表示单精度,双精度和扩展精度值。C++标准制定了一个浮点数有效位数的最小值,然而大多数编译器都实现了更高的精度。通常,float以一个字(32比特)来表示,double以两个字来表示。
练习2.2 计算按揭贷款时,对于利率,本金和付款分别应选择什么数据类型?
建议执行浮点数运算选用double。
2.1.2类型转换
- 当我们赋给无符号类型一个超出它表示范围的值时,结果是初始值对无符号类型表示数值总数取模后的余数。unsiged char c=-1; //假设char占8比特,c的值为255。 int的范围是-2147483648~-2148483647,而unsigned int的范围是0~4294967295.这一条是这一小节的重点。提示:切勿混用带符号类型和无符号类型。
练习2.3
2.1.3 字面值常量
一个形如42的值被称作字面值常量,这样的值一望而知。每个字面值常量都对应一种数据类型,字面值常量的形式和值决定了它的数据类型。
练习2.5
(a) 'a' 字符字面值; L'a' 宽字符型字面值 ''a'' 字符串字面值 L"a" 宽字符串字面值
3.14L //扩展精度浮点型字面值,类型是long double
2.2.1 变量定义
初始化不是赋值,初始化的含义是创建一个变量时赋予其一个初始值,而赋值的含义是把对象的当前值擦除,而以一个新值来替代。
列表初始化的问题,指定-std=C++11参数l来使编译器支持C++11。
默认初始化:定义于任何函数体之外的变量被初始化为0。定义在函数体内部的内置类型变量将不被初始化。一个未被初始化的内置类型变量的值是未定义的,如果试图拷贝或以其他形式访问此类值将引发错误。每个类各自决定其初始化对象的方式。
为了支持分离式编译,C++语言将声明和定义区分开。声明使得名字为程序所致。而定义负责创建与名字关联的实体。变量能且只能被定义一次,但是可以被多次声明。
extern int i; //声明i而非定义i
int j;//声明并定义j
2.2.4 名字的作用域
作用域是程序的一部分,在其中名字有其特定的含义。C++语言中大多数作用域都以花括号分割。名字的有效区域始于名字的声明语句,以声明语句所在的作用域末尾为结束。
2.3复合类型
复合类型是指基于其他类型定义的类型。目前我们接触的声明语句中,声明符其实就是变量名。 一般在初始化变量时,初始值会被拷贝到新建的对象中。然而定义引用时,程序把引用和它的初始值绑定在一起,而不是将初始值拷贝给引用。因为引用本身不是一个对象,所以不能定义引用的引用。
何为对象?通常情况下,对象是指一块能存储数据并具有某种类型的内存空间。
练习2.15 (a)合法 (b)不合法, 引用只能绑定在对象上,而不能与字面值绑定在一起。c合法 d不合法,必须初始化引用。
练习2.16 均合法
练习2.17 输出10 10
2.3.2 指针
int &r=i; // &紧随类型名,因此是声明的一部分,r是一个引用
预处理器是运行于编译过程之前的一段程序。
练习2.23 给定指针p,你能知道它是否指向一个合法的对象吗?如果能,叙述判断的思路。 p指向的是否是空指针?
练习2.24 void*是一种特殊的指针类型,可用于存放任意对象的地址。我们对该地址中到底是个什么类型的对象并不了解。
变量的定义包括一个基本数据类型和一组声明符。类型修饰符是声明符的一部分。
- 如果想在多个文件之间共享const对象,必须在变量的定义之前添加extern关键字。
const限定符:因为const对象一旦创建后其值就不能再改变,所以const对象必须初始化。
- 一般来说,引用的类型必须与其所引用对象的类型一致。但是有两个例外,一种就是在初始化常量引用时允许用任意表达式作为初始值,只要该表达式的结果可以转换成引用的类型即可。
- 指针的类型必须与其所指向对象的类型一致,但是有两个例外,其中一个例外情况是允许令一个指向常量的指针指向一个非常量的对象。比如,编译以下4行是正确的.
- const指针,把*放在const关键字之前用以说明指针是一个常量。 常量指针必须初始化,而且一旦初始化,则它的值就不能再改变了。
const double pi=3.14;
const double *cptr=π
double dval=3.14;
cptr=&dval; //(const double temp=dval; const double *cptr=&dval)
练习2.27: a不合法 c合法,这是一种引用的类型必须要和其所引用的对象的类型一致例外情况,是一个字面值。 d e合法如果const int i2=1024的话。 f const int &const r2不合法, 必须初始化引用r2. g合法
练习2.28 a不合法,如果不是外部的,则必须初始化常量对象。b不合法,必须初始化常量对象p2。 c不合法,必须初始化常量对象。d也不合法。e是合法的,const int *p; p是一个指向常量的指针。
2.4.3 顶层const
用名词顶层const表示指针本身是个常量,而用名词底层const表示指针指向的对象是一个常量。更一般的,顶层const可以表示任意的对象是常量。指针类型既可以是顶层const也可以是底层const。
练习2.32 不合法,int类型的值不能用来初始化int *类型的实体。
- 常量表达式是指值不会改变并且在编译过程中就能得到计算结果的表达式
2.5处理类型
2.5.1 类型别名
类型unsigned int可以缩写为unsigned。
2.5.2 auto类型
练习 2.33: a可以复制 b也可以 c也可以 d是一个整型指针 ,不合法,不能将int类型赋给int *. e是一个指向整数常量指针,忽略了顶层const?? 不合法,不能讲int类型的值分配到const int *类型。; 可以将引用的类型设置为auto,g是一个整型常量引用。不合法,不能给常量赋值。
练习2.35
const int i=42;
auto j=i;// i的顶层const特性被忽略, j是一个整数
const auto &k=i;//k是一个常量引用,不可给k赋值,因为不能给常量赋值
auto *p=&i; //p是一个整型指针
const auto j2=i, &k2=i; //j2是const int, k2是一个常量引用
decltype,返回变量或表达式的类型,或函数的返回类型
练习 2.36: c是int, d是int& 结束时出 a=4 b=4 c=4 d=4
练习2.38:int a=3; atuo b=3;
int a=3; decltype(a) c=a;
练习2.39:
2.6.3 编写自己的头文件
预处理器:在C++编译的过程中执行的一段程序。
确保头文件多次包含仍能安全工作的常用技术是预处理器技术。