1、基本类型
1.1、基本内置类型
基本算数类型:
类型 | 含义 | 最小尺寸 |
---|---|---|
bool | 布尔类型 | 8bits |
char | 字符 | 8bits |
wchar_t | 宽字符 | 16bits |
char16_t | Unicode字符 | 16bits |
char32_t | Unicode字符 | 32bits |
short | 短整型 | 16bits |
int | 整型 | 16bits (在32位机器中是32bits) |
long | 长整型 | 32bits |
long long | 长整型 | 64bits(是在C++11中新定义的) |
float | 单精度浮点数 | 6位有效数字 |
double | 双精度浮点数 | 10位有效数字 |
long double | 扩展精度浮点数 | 10位有效数字 |
1.2、如何选择类型
- 当明确知晓数值不可能是负数时,选用无符号类型;
- 使用
int
执行整数运算。一般long
的大小和int
一样,而short
常常显得太小。除非超过了int
的范围,选择long long
。 - 算术表达式中不要使用
char
或bool
。 - 浮点运算选用
double
。
1.3、字面值常量
一个形如42
的值被称作字面值常量(literal)。
- 整型和浮点型字面值。
- 字符和字符串字面值。
- 使用空格连接,继承自
C
。 - 字符字面值:单引号,
'a'
。 - 字符串字面值:双引号,
"Hello World"
- 使用空格连接,继承自
- 转义序列。
\n
、\t
等。 - 布尔字面值。
true
,false
。 - 指针字面值。
nullptr
。
2、变量
变量提供一个具名的、可供程序操作的存储空间。 C++
中变量和对象一般可以互换使用。
2.1、变量定义(define)
定义形式: 类型说明符(type specifier) + 一个或多个变量名组成的列表。如int sum = 0, value, units_sold = 0;
(最好不要采用这种方式,可读性太差)
初始化(initialize):对象在创建时获得了一个特定的值。
- 初始化不是赋值!
- 初始化 = 创建变量 + 赋予初始值
- 赋值 = 擦除对象的当前值 + 用新值代替
- 列表初始化:使用花括号
{}
,如int units_sold{0}
; - 默认初始化:
- 定义时没有指定初始值会被默认初始化;
- 在函数体内部的内置类型变量将不会被初始化。
- 建议初始化每一个内置类型的变量。
2.3、声明 vs 定义
- 为了支持分离式编译,
C++
将声明和定义区分开。声明使得名字为程序所知。定义负责创建与名字关联的实体。 - extern: 只是说明变量定义在其他地方。
- 只声明而不定义: 在变量名前添加关键字 extern,如extern int i;。但如果包含了初始值,就变成了定义:extern double pi = 3.14;
- 变量只能被定义一次,但是可以多次声明。
- 名字的作用域(namescope)
3、左值和右值
- 左值(l-value)
可以
出现在赋值语句的左边或者右边,比如变量; - 右值(r-value)
只能
出现在赋值语句的右边,比如常量。
4、复合类型
4.1、引用
- 引用: 引用是一个对象的别名,引用类型引用(refer to)另外一种类型。如int &refVal = val;。
- 引用必须初始化。
- 引用和它的初始值是绑定bind在一起的,而不是拷贝。
4.2、指针
- 是一种 "指向(point to)"另外一种类型的复合类型。
- 定义指针类型:
int *ip1
;,从右向左读,ip1
是指向int类型的指针。 - 指针存放某个对象的地址。
- 获取对象的地址:
int i=42; int *p = &i;
。&
是取地址符。 - 指针的值的四种状态:
- 指向一个对象;
- 指向紧邻对象的下一个位置;
- 空指针;
- 无效指针。
- 指针访问对象:
cout << *p;
, *是解引用符。 - 空指针不指向任何对象。
void*
指针可以存放任意对象的地址。- 其他指针类型必须要与所指对象严格匹配。
- 两个指针相减的类型是
ptrdiff_t
。 - 建议:初始化所有指针。
5、const限定符
动机:希望定义一些不能被改变值的变量。
5.1、初始化和const
- const对象必须初始化,且不能被改变。
- const变量默认不能被其他文件访问,非要访问,必须在指定const前加extern。
5.2、const的引用
- reference to const(对常量的引用):指向const对象的引用,如
const int ival=1; const int &refVal = ival;
,可以读取但不能修改refVal。 - 临时量(temporary)对象:当编译器需要一个空间来暂存表达式的求值结果时,临时创建的一个未命名的对象。
- 对临时量的引用是非法行为。
5.3、指针和const
- pointer to const(指向常量的指针):不能用于改变其所指对象的值, 如
const double pi = 3.14; const double *cptr = π
。 - const pointer:指针本身是常量,如
int i = 0; int *const ptr = &i;
5.4、顶层const
- 顶层const:指针本身是个常量。
- 底层const:指针指向的对象是个常量。拷贝时严格要求相同的底层const资格。
5.5、constexpr
和常量表达式
● 常量表达式:指值不会改变,且在编译过程中就能得到计算结果的表达式。
● C++11新标准规定,允许将变量声明为constexpr
类型以便由编译器来验证变量的值是否是一个常量的表达式。
6、处理类型
6.1、类型别名
- 传统别名:使用typedef来定义类型的同义词。
typedef double wages;
- 新标准别名:别名声明(alias declaration):
using SI = Sales_item;
(C++11)
6.2、auto类型说明符
auto
类型说明符:让编译器自动推断类型。int i = 0, &r = i; auto a = r;
推断a的类型是int。- 会忽略顶层const。
const int ci = 1; const auto f = ci;
推断类型是int
,需要自己加const
;- C++11
6.3、decltype类型指示符
- 从表达式的类型推断出要定义的变量的类型;
decltype
:选择并返回操作数的数据类型;decltype(f()) sum = x;
推断sum
的类型是函数f
的返回类型;- 不会忽略顶层const;
- C++11
6.4、编写自己的头文件
- 头文件通常包含那些只能被定义一次的实体:类、
const
和constexpr
变量。
预处理器概述: - 预处理器(preprocessor):确保头文件多次包含仍能安全工作。
- 当预处理器看到
#include
标记时,会用指定的头文件内容代替#include
。 - 头文件保护符(header guard):头文件保护符依赖于预处理变量的状态:已定义和未定义。
#ifndef SALES_DATA_H
#define SALES_DATA_H
strct Sale_data{
...
}
#endif