2.变量和基本类型
变量和基础类型
1 基本内置类型
- C++是一种静态数据类型语言,在编译时进行类型检查
- C++定义了:算术类型(arithmetic)、空类型(void)
1.1 算术类型
类型 | 含义 | 最小尺寸(bit) | 说明 |
---|---|---|---|
bool |
布尔类型 | 未定义 | 取值为真 (true)或假 (false) |
char |
字符 | 8 位 | 1 个 char 的大小和一个机器字节一样 |
wchat_t |
宽字符 | 16 位 | 用于扩展字符集,确保可以存放机器最大,扩展字符集中的任意一个字符 |
char16_t |
Unicode 字符 | 16 位 | 用于扩展字符集,为 Unicode 字符集服务 |
char32_t |
Unicode 字符 | 32 位 | 用于扩展字符集,为 Unicode 字符集服务 |
shor |
短整型 | 16 位 | |
int |
整型 | 16 位 | 一个 int 至少和一个 short 一样大,在 32 位机器上是 32bit |
long |
长整型 | 32 位 | 一个 long 至少和一个 int 一样大 |
long long |
长整型 | 64 位 | C++11 中新定义,一个 long long 至少和一个 long 一样大 |
float |
单精度浮点数 | 6 位有效数字 | |
double |
双精度浮点数 | 10 位有效数字 | |
long double |
扩展精度浮点型 | 10 位有效数字 | 常常用于有特殊浮点需求的硬件 |
计算机以比特序列存储数据,每个比特非 0 即 1, 可寻址的最小内存块称为“字节(byte)”,内存的基本单元称为“字(word) 大多数机器的字节由 8 比特构成,字则由 32 或 64 比特构成
常用数据类型对应字节数可用如 sizeof(char),sizeof(char*)等得出
32 位编译器:
char :1个字节
char*(即指针变量): 4个字节(32位的寻址空间是2^32, 即32个bit,也就是4个字节。同理64位编译器8个字节)
short int : 2个字节
int: 4个字节
unsigned int : 4个字节
float: 4个字节
double: 8个字节
long: 4个字节
long long: 8个字节
unsigned long: 4个字节
64 位编译器:
char :1个字节
char*(即指针变量): 8个字节
short int : 2个字节
int: 4个字节
unsigned int : 4个字节
float: 4个字节
double: 8个字节
long: 8个字节
long long: 8个字节
unsigned long: 8个字节
综上:个人总结,32 位编辑器、64 位编辑器, 只是 char*类型的大小变化了,即指针;另外发现只有 unsigned long 类型变为 8 字节, 其他类型没变。
1.1.1 无符号类型
- int、 short、 long 和 long long 都是带符号的,前面加上 unsigned 就可以得到无符号类型,例如 unsigned long
- unsigned int 可以缩与成 unsigned
- char 比较特殊,类型分为三种:char、signed char、 unsigned char
- char 是 signed char 或 unsigned char 的其中一种(编译器决定)
1.1.2 如何选择类型
- 1.当明确知晓数值不可能是负数时,选用无符号类型;
- 2.使用
int
执行整数运算。一般long
的大小和int
一样,而short
常常显得太小。除非超过了int
的范围,才选择long long
。 - 3.算术表达式中不要使用
char
或bool
。 - 4.浮点运算选用
double
。
1.2 类型转换
- 非布尔型赋给布尔型,初始值为 0 则结果为 false,否则为 true。
- 布尔型赋给非布尔型,初始值为 false 结果为 0,初始值为 true 结果为 1。
bool b = 42; // b为真
int i = b; // i=1
i = 3.14; // i=3
double pi = i; // pi的值为3.0
unsigned char c = -1; // 假设char占8比特,c的值为255
signed char c2 = 256; // 假设char占8比特,c2的值未定义
注意:char 在一些环境是有符号的,而在另一些环境是无符号的,所以这里面程序移植后可能会有问题
注意:切勿混用带符号类型和无符号类型,比如让两个数相加,转换由编译器决定,程序结果不受控(编译器可能不同)
1.3 字面值常量
一个型如 42 的值被称为字面值常量 (literal)
字面值常量的形式和值决定了它的数据类型。
1.3.1 整形和浮点型字面值
- 可以将整形写成十进制、八进制或十六进制
20 //十进制
024 //八进制
0x14//十六进制
- 浮点型字面值是一个 double 类型的值,表现为一个小数或科学计数法的指数形式
3.14159
3.14169E0
0.
0e0
.001
- 字符和字符串字面值
'a'//char
"Hello World" //string
- 转义序列,C++定义的转义序列包括:
//常见转义字符
\n
\t
\a
\v
\b
\?
\r
\f
- 泛化的转义序列,其形式是\x 后紧跟 1 个或多个十六进制的数字,或后面紧跟 1、2 或 3 个八进制的数字。假设使用的是 Latin-1 字符集,以下是一些示例:
\7 响铃
\12 换行
\40 空格
\0 空字符
\115 字符M
\x4d 字符M
1.3.2 指定字面值的类型(显式)
- 字符和字符串字面值
前缀 | 含义 | 类型 |
---|---|---|
u | Unicode 16 字符 | char16_t |
U | Unicode 32 字符 | char32_t |
L | 宽字符 | wchat_t |
u8 | UTF8(仅用于字符串字面常量) | char |
- 整型字面值
后缀 | 最小匹配类型 |
---|---|
u or U | unsigned |
l or L | long |
ll or LL | long long |
- 浮点型字面值
后缀 | 类型 |
---|---|
f or F | float |
l or L | long double |
1.3.3 字面值常量(总结)
- 一个形如
42
的值被称作字面值常量(literal)。- 整型和浮点型字面值。
- 字符和字符串字面值。
- 使用空格连接,继承自 C。
- 字符字面值:单引号,
'a'
- 字符串字面值:双引号,
"Hello World""
- 分多行书写字符串。
std:cout<<"wow, a really, really long string" "literal that spans two lines" <<std::endl;
- 转义序列。
\n
、\t
等。 - 布尔字面值。
true
,false
。 - 指针字面值。
nullptr
字符串型实际上时常量字符构成的数组,结尾处以
'\0'
结束,所以字符串类型实际上长度比内容多 1。
2 变量
- 变量:具有类型、具有名称、可操作的存储空间。
- 类型决定了变量所需要的内存空间、布局方式、以及能够表示值的范围。
int sum=0,value;
string book;
Sales_item item;
对于 C++程序员来说,变量(variable)和对象(object)一般是可以互换的。
2.1 变量定义
- 定义形式:类型说明符(type specifier) + 一个或多个变量名组成的列表。如
int sum = 0, value, units_sold = 0;
- 初始化(initialize):对象在创建时获得了一个特定的值。
- 初始化不是赋值!:
- 初始化 = 创建变量 + 赋予初始值
- 赋值 = 擦除对象的当前值 + 用新值代替
- 列表初始化:使用花括号
{}
,如int units_sold{0};
- 默认初始化:定义时没有指定初始值会被默认初始化;在函数体内部的内置类型变量将不会被初始化。
- 建议初始化每一个内置类型的变量。
- 初始化不是赋值!:
2.1.1 传统初始化 和 列表初始化
作为 C++(11)新标准的一部分,使用花括号来初始化变量(列表初始化)得到了全面应用;
旧版本使用={} ,新版本直接使用{}
int units_sold = 0;
int units_sold = {0}; //列表初始化
int units_sold{0}; //列表初始化
int units_sold(0);
- 如果我们使用列表初始化,且初始值存在丢失信息的风险,则编译器将报错。
double d=3.14;
int a{d};//报错:转换未执行,因为存在丢失信息的风险
int a=d; //正常:转换执行,且确实丢失了部分值
2.1.2 默认初始化
- 如果定义变量没有定义初始值,则变量被赋予默认值。
- 默认值是由变量类型决定的,同时定义变量的位置也会有影响。
- 内置类型:由定义的位置决定,函数体之外初始化为 0
- 每个类各自决定其初始化对象的方式
未初始化的变量含有一个不确定的值,将带来无法预计的后果,应该避免。
2.2 变量声明和定义的关系
- C++支持分离式编译,每个文件可以单独编译,为了支持分离式编译,C++将声明和定义分开
- C++是一种静态类型语言。要求在使用某个变量之前必须先声明。
- 声明使得(变量)名字为程序所知,定义负责创建与名字关联的实体
- 如果想声明一个变量而非定义它,就在变量名前添加 extern(外部的)关键字,而且不要显式的初始化。
- 声明在前,定义在后
extern 不是定义,是引入(声明)在其它源文件中定义的非 static 全局变量
变量能且只能定义一次,但可以被声明多次。
定义了一个函数,需要在其它文件中使用,那么需要在其它文件中声明这个函数,所以定义只有一次,声明可以多次
2.3 标识符
C++标识符(identifier)由字母、数字和下划线组成,其中必须以字母或下划线开头。标识符的长度没有限制,但对大小写敏感。 C++语言保留了一些名字供语言本身使用,这些名字不能作为标识符。
2.4 名字的作用域
- 同一个名字如果出现在程序的不同位置,也可能指向不同的实体。
- C++中大多数作用域都以花括号分隔。
- 名字的有效区域始于名字的声明语句,以声明语句所在的作用域末端为结束。
- 嵌套作用域中,允许在内层作用域重新定义外层作用域已有的名字,名字的有效区域,记住上一个规则,进行推断即可
建议:如果函数有可能用到某个全局变量,则不宜再定义一个同名的局部变量。 建议:当你第一次使用变量时再定义它
2.5 左值和右值
- 左值(l-value)可以出现在赋值语句的左边或者右边,比如变量;
- 右值(r-value)只能出现在赋值语句的右边,比如常量或常量表达式;
3 复合类型
是指基于其它类型定义的类型,提供对象之间的间接访问
3.1 引用(reference)
引用是为对象起的别名
- 定义引用时,把引用和它的初始值绑定在一起,而不是将初始值拷贝给引用
- 引用和它的初始值是绑定 bind在一起的,而不是拷贝。一旦定义就不能更改绑定为其他的对象
- 可以理解引用是一张贴纸,贴在对象盒子上的,一个对象盒子上可以有很多贴纸(别名、引用)
- 引用本身并不是对象,所以不能定义引用的引用
- 引用必须初始化
- 引用只能绑定到对象上,不能与字面值或某个运算表达式的结果绑定在一起
- 小技巧,声明为引用类型可以避免对元素的拷贝,如下,如 string 特别大时可以节省大量时间。
vector<string> text;
for(const auto &s: text){
cout<<s;
}
C++11 中新增了 “右值引用”;当我们使用术语“引用”时,一般指的是“左值引用”
补充一句,右值引用一般用于内置类,后续 13.6 展开讲
3.2 指针(pointer)
指针是对地址的封装,本身是一个对象
- 定义指针类型的方法是将声明符写成*d 的形式
- 如果一条语句中定义了几个指针变量,每个变量前面都必须加上*符号
- 和其他内置类型一样,在块作用域内定义指针如果没有初始化,将拥有一个不确定的值
- 可以使用取地址符(运算符&)获取指针所封装的地址
- 可以使用解引用符(运算符*)利用指针访问对象
- 解引用(*)操作仅适用于那些确实指向了某个对象的有效指针,空指针和野指针会有问题
注意:引用不是对象,不存在地址,所以不能定义一个指针指向引用
在声明(左值)中,*和&用于组成复合类型,他们是表示指针和引用;
在表达式(右值)中,*和&他们是运算。他们是表示取值和取址
3.2.1 空指针(null pointer)
- 不指向任何对象
- 在使用一个指针之前,可以首先检查它是否为空
- C++11 推荐尽量使用 nullptr,不使用 NULL
- 建议初始化所有指针,不确定则初始化为 nullptr
int *p1 = nullptr;//c++11
int *p2 = 0;
int *p3 = NULL;//需要#include cstdlib
int p1 = 0;//正常
int zero = 0;
p1 = zero;//错误:类型不匹配
为了避免野指针,应该在指针使用前确定指针的值;很多回调函数中不能确定值,建议使用 void 指针
tips:很多时候一条賦值语句到底是改变了指针的值还是改变了指针所指对象的值,不好确定,最好的办法是记住赋值号永远改变左侧的对象!!根据运算符的优先级确认左侧对象的类型是什么!!
3.2.2 指针与 bool
- 指针的值等于 0,bool=FALSE
- 指针的值不等于 0,bool=TRUE
- 两个指针比较,存放的地址值是否相同
3.2.3 void * 指针
纯粹的地址封裝,与类型无关。可以用于存放任意对象的地址。
不能直接操作 void 指针所指的对象,因为不知道对象所占空间的字节大小
3.2.4 小小讨论
int* i=1;//风格1
int *j=2;//风格2
int& i=refVal;//风格1
int &j=refVal;//风格2
*& 符号靠近类型符和靠近声明符,形成了两种风格,编译器都允许,以上两种风格各有优点。
^_^ 我个人倾向于风格 2 ,因为它让我觉得*i 是一个 int,所以 i 是一个 int pointer。int *i,j,k
风格 2 遇到这种情况可读性高
3.3 理解复合类型的声明
面对一条比较复杂的指针或引用的声明语句时,从右向左阅读有助于弄清楚它的真实含义。
程序员容易迷惑于基本数据类型和类型修饰符的关系,其实后者不过是声明符的一部分
3.3.1 指针的指针
通过*的个数可以区分指针的级别。
int ival = 100;
int *pi = &ival;
int **ppi = π // ppi指向一个int类型的指针
3.3.2 指针的引用
指针是对象,可以定义引用
int i = 100;
int *p;
int *&r = p; // r是一个对指针p的引用
int* &r = p; // r是一个对指针p的引用,写成这样比较好理解
r = &i; // r是p的一个别名(引用),等同于p=&i
*r = 0; // r是p的一个别名(引用),等同于*p=i
4 const 限定符
- 把变量定义成一个常量(其实更好的理解是只读变量,不能被改变值的变量)
- 使用 const 对变量的类型加以限定,变量的值不能被改变。
- const 对象必须初始化(其他时候不能出现在等号左边)
- const 与 define 类似,但是比 define 灵活,同样是编译器将编译过程中用到 const 变量的地方,替换掉
//不能更改const只读变量的值
const int j = 100;
j = 200;//error,cannot assign to variable 'j' with const-qualified type 'const int'
//必须初始化
const int i=100;//normal
const int k;//default initialization of an object of const type 'const int'
默认状态下,const 对象作用域是仅在文件内有效
如果想在多个文件之间共享 const 对象,必须在变量的定义之前添加 extern 关键字
4.1 const 的引用(常量引用)
对常量的引用
判断常量的引用是否正确,判断是否有更改这个常量(const)的风险
声明引用的 const ,都是底层 const
const int ci = 100;
const int &r1 = ci; //正确
r1 = 200; //错误,尝试修改const变量
int &r2 = ci; //错误,ci是const变量,存在通过r2改变ci(const)的风险
//不能将常量(const &r1)赋值给变量引用
int &r3 = r1;
对于引用的赋值会发生类型转换的情况,要注意 非常量限定 ,这名词太拽了,简单就是说,可以右值直接类型转换后赋值给常量引用(const);不能右值转换后赋值给变量引用,因为这样的引用实际上是临时变量的别名,没有意义。
double dval = 3.14;
const int &ri = dval;//正常
int &ri = dval;//错误
// 第三行报错,因为底层执行是
// int temp = (int)dval;
// int &ri = temp;
// 所以引用ri是temp的别名,如果引用是变量,更改temp这个没有意义,所以编译器直接报错,阻止了这种情况的发生
// 第二行正常的原因是,ri是常量(const),底层执行是,const int &ri = 3;
4.2 指针和 const
4.2.1 指向常量的指针(pointer to const)
- 常量值不能改(指针指向的值)
- 指针值可以改(指针的地址 pci 可以更改)
- 底层 const
int const *pci;
const int *pic; // the same
4.2.2 const 指针(const pointer)
- 指针是常量(指针地址 cpi 不能改)
- 指针解引用的值可以改
- 顶层 const
int * const cpi;
注意:const 指针必须初始化
指针当然最好都要初始化~
4.3 顶层 const 和底层 const
- 顶层 const:变量本身是常量(const)
- 底层 const:指针所指向的对象是常量(const),拷贝时严格要求对方也是底层 const。
const AA * aa;
// 这是一个底层 const。您正确地指出,您不能通过 aa 指针来修改 AA 对象的内容(例如 aa->i,假设 i 是 AA 类的一个成员)。
// 但是,您可以更改 aa 本身,使其指向另一个 AA 对象。
AA * const aa;
// 这是一个顶层 const。您正确地指出,指针 aa 本身是常量,所以您不能修改它的值(即它不能被重新赋值以指向其他的 AA 对象)。
// 但是,您可以通过这个指针来修改 AA 对象的内容。
// 所以,总结一下:
// 底层 const 影响到指针所指向的对象。
// 顶层 const 影响到指针本身。
// 您的理解是对的,只是通常我们说 "底层 const 限制了我们不能通过指针修改所指对象" 和 "顶层 const 限制了指针本身不能被修改"。
4.4 constexpr 和常量表达式
- 常量表达式(const expression)是指:值不会改变并且在编译过程就能得到计算结果的表达式。
const int max_files = 20;//是
const int min_files = get_size();//不是,后面会学习 constexpr 函数来初始化 constexpr 变量
4.4.1 constexpr 变量
- C++11 标准规定,允许将变量声明为 constexpr 类型,全称 constant expression,译为常量表达式,以便由编译器来验证变量的值是否是一个常量表达式。
- 一定是一个 常量
- 必须用常量表达式初始化
需要在编译时就得到计算,声明 constexpr 时用到的类型必须显而易见,容易得到(称为:字面值类型)
自定义类型(例如:Sales_item)、IO 库、string 等类型不能被定义为 constexpr
- 指针和 constexpr
- constexpr 限定符仅对指针有效,对指针所指对象无关
- constexpr 修饰的是顶层 const
const int * p = nullptr; // 指向常量的指针(pointer to const),底层 const
constexpr int * q = nullptr; // 指向整数的常量指针(const pointer),顶层 const
建议:如果你认为变量是一个常量表达式,那就把它声明成 constexpr 类型
5 处理类型
随着程序越来越复杂,程序中的用到的类型也越来越复杂。
- 无法明确表示真实含义。
- 搞不清楚变量到底需要什么类型。
5.1 类型别名
目的:提高可读性
- C 传统别名:使用typedef来定义类型的同义词。
typedef double wages;
- 新标准别名:别名声明(alias declaration):
using SI = Sales_item;
(C++11)
typedef double wages;
typedef wages base,*p;//base是double的同义词,p是double的同义词
using SI = Sales_item;//C++11,别名声明
wages hourly,weekly;
SI item;//等价于Sale_item item
对于指针这样的复合类型,类型别名的使用可能会产生意想不到的结果:
// 对于复合类型(指针等)不能代回原式来进行理解
typedef char *pstring; // pstring是char*的别名
const pstring cstr = 0; // 指向char的常量指针
// 如改写为const char *cstr = 0;不正确,为指向const char的指针
// 辅助理解(可代回后加括号)
// const pstring cstr = 0;代回后const (char *) cstr = 0;
// const char *cstr = 0;即为(const char *) cstr = 0;
5.2 auto 类型说明符
C++11,让编译器通过初始值推断变量的类型
auto 会忽略顶层 const,底层 const 会保留下来
auto item = val1 + val2;//根据val1和val2相加后的类型,推导item的类型
auto sz = 0,pi=3.14;//错误:类型推导需要一致性
const auto f = ci; //明确指出 auto 类型是顶层 const
C++ auto 提供了灵活性,使用自动推断类型最好提前知道可能是哪些类型,避免一些风险
5.3 decltype 类型指示符
- Declare type 的缩写
- 选择并返回操作数的数据类型
- 只要数据类型,不要其值
decltype(f()) sum = x; // sum的类型就是函数f返回的类型
const ci = 0, &cj = ci;
decltype(ci) x = 0;
decltype(cj) y = x; // y的类型是 const int &,此时y必须初始化
- 从表达式的类型推断出要定义的变量的类型。
- decltype:选择并返回操作数的数据类型。
decltype(f()) sum = x;
推断sum
的类型是函数f
的返回类型。- 不会忽略
顶层const
。 - 如果对变量加括号,编译器会将其认为是一个表达式,如 int i,则 decltype((i))得到结果为 int&引用。decltype(i)才是 int 类型
- 赋值是会产生引用的一类典型表达式,引用的类型就是左值的类型。也就是说,如果 i 是 int,则表达式 i=x 的类型是 int&。
- decltype(引用)结果是引用,所以必须初始化
C++11
新特性,需要编译器支持
6 自定义数据结构
一组数据和函数的集合
6.1 定义 Sales_data 类型
类定义:class 或者 struct
- 二者默认的继承、访问权限不同
- struct 是 public 的,class 是 private 的
- 注意结尾的分号
struct Sales_data
{
std::string bookNo;
double revenue = 0.0;
};
6.2 使用 Sales_data 类
# include <iostream>
# include <string>
# include "Sales_data.h"
int main()
{
Sales_data data1, data2;
// code to read into data1 and data2
double price = 0; // price per book, used to calculate total revenue
// read the first transactions: ISBN, number of books sold, price per book
std::cin >> data1.bookNo >> data1.units_sold >> price;
// calculate total revenue from price and units_sold
data1.revenue = data1.units_sold * price;
// read the second transaction
std::cin >> data2.bookNo >> data2.units_sold >> price;
data2.revenue = data2.units_sold * price;
// code to check whether data1 and data2 have the same ISBN
// and if so print the sum of data1 and data2
if (data1.bookNo == data2.bookNo) {
unsigned totalCnt = data1.units_sold + data2.units_sold;
double totalRevenue = data1.revenue + data2.revenue;
// print: ISBN, total sold, total revenue, average price per book
std::cout << data1.bookNo << " " << totalCnt
<< " " << totalRevenue << " ";
if (totalCnt != 0)
std::cout << totalRevenue/totalCnt << std::endl;
else
std::cout << "(no sales)" << std::endl;
return 0; // indicate success
} else { // transactions weren't for the same ISBN
std::cerr << "Data must refer to the same ISBN"
<< std::endl;
return -1; // indicate failure
}
}
7 编写自己的头文件
建议:把结构体和类定义和全局变量声明在头文件中
# ifndef SALES_DATA_H
# define SALES_DATA_H
# include <string>
struct Sales_data {
std::string bookNo;
unsigned units_sold = 0;
double revenue = 0.0;
};
# endif
预处理器(preprocessor),继承自 C 语言 在编译之前执行的代码。确保头文件多次包含仍能安全工作
这里的作用是:头文件保护
- 预处理变量有两种状态
- 已定义#define SALES_DATA_H
- 未定义#ifndef SALES_DATA_H
- 避免重复引入某个头文件
- 头文件保护符的名称需要唯一,且保持全部大写。养成良好习惯,不论是否该头文件被包含,要加保护符。
8 小结
类型是 C++编程的基础。
类型规定了其对象的存储要求和所能执行的操作。C++语言提供了一套基础内置类型,如 int 和 char 等,这些类型与实现它们的机器硬件密切相关。类型分为非常量和常量,一个常量对象必须初始化,而且一旦初始化其值就不能再改变。比外,还可以定义复合类型,如指针和引用等。复合类型的定义以其他类型为基础。
c++语音允许用户以类的形式自定义类型。C++库通过类提供了一套高级抽象类型,如输入输出和 string 等。
9 术语表
地址(address): 是一个数字,根据它可以找到内存中的一个字节
别名生命(alias declaration): 为另一种类型定义一个同义词:使用 ”名字 = 类型“ 的格式将名字作为该类型的同义词。
算术类型(arithmetic type): 布尔值,字符,整数,浮点数等内置类型。
数组(array): 是一种数据结果,存放着一组未命名的对象,可以通过索引来访问这些对象。
auto: 是一种类型说明符,通过变量的初始值来推断变量的类型。
基本类型(base type): 是类型说明符,可以用 const 来修饰,在声明语句中位于声明符之前。基本类型提供了最常见的数据类型,以此为基础构建声明符。
绑定(bind): 令某个名字与给定的实体关联在一起,使用该名字也就是使用该实体。例如,引用就是将某个名字与某个对象绑定在一起。
字节(byte): 内存中可寻址的最小单位,大多数机器的字节占 8 位。
类成员(class member): 类的组成部分。
复合类型(class member): 是一种类型,它的定义以其他类型位基础。
const: 是一种类型修饰符,用于说明永不改变的对象。const 对象一旦定义就无法再赋新值,所以必须初始化。
常量指针(const pointer): 是一种指针,它的值永不改变。
常量引用(const reference): 是一种习惯叫法,含义是指向常量的引用。
常量表达式(const expression): 能在编译时计算并获取结果的表达式。
constexpr: 是一种函数,用于代表一条常量表达式。
转换(conversion): 一种类型的值转变成另一种类型值的过程。C++语言支持内置类型之间的转换。
数据成员(data member): 组成对象的数据元素,类的每一个对象都有类的数据成员的一份拷贝。数据成员可以在类内部声明的同时初始化。
声明(declaration): 声称存在一个变量,函数或是别处定义的类型。名字必须在定义或声明之后才能使用。
声明符(declarator): 是声明的一部分,包括被定义的名字和类型修饰符,其中类型修饰符可以有也可以没有。
decltype: 是一个类型说明符,从变量或表达式推断得到类型。
默认初始化(default initalization): 当对象没被显式的赋予初始值时执行的初始化行为。由类本身负责执行的类对象的初始化行为。全局作用域的内置类型对象初始化为 0; 局部作用域的对象未被初始化即拥有未定义的值。
定义(definition): 为某一种特定类型的变量申请存储空间,可以选择初始化该变量。名字必须在定义或声明之后才能使用。
**转义字符(escape sequence):**字符特别时那些不可打印字符的替代形式。转义以反斜线开头,后面紧跟一个字符,或者不多于 3 个八进制数字,或者字母 x 加上 1 个十六进制数。
全局作用域(global scope): 位于其他所有作用域之外的作用域。
头文件保护符(header guard): 使用预处理变量防止头文件被某个文件重复包含。
标识符(identifier): 组成名字的字符序列,标识符对大小写敏感。
类内初始值(in-class initializer): 在声明类的数据成员时同时提供的初始值,必须置于等号右侧或花括号内。
在作用域内(in scope): 名字在当前作用域内可见。
被初始化(initalized): 变量在定义的同时被赋予初始值,变量一般都应该被初始化。
内层作用域(inner scope): 嵌套在其他作用域之内的作用域。
整型(iniegral type): 参见算术类型。
列表初始化(list initialization): 利用花括号把一个或多个初始值放在一起的初始化形式。
字面值(literal): 是一个不能改变的值,如数字,字符,字符串等。单引号内的是字符字面值,双引号内的是字符串字面值。
局部作用域(local scope): 是块作用域的习惯叫法。
底层 const(low-level const): 一个不属于顶层的 const,类型如果由底层常量定义,则不能被忽略。
成员(member): 类的组成部分
不可打印字符(nonprintable character): 不具有可见形式的字符,如控制符,退格,换行符等。
空指针(null pointer): 值为 0 的指针,空指针合法但是不指向任何对象。
nullptr: 是表示空指针的字面值常量。
对象(object): 是内存的一块区域,具有某种类型,变量是命名了的对象。
外层作用域(outer scope): 嵌套着倍的作用域的作用域。
指针(pointer): 是一个对象,存放着某个对象的地址,或者某个对象存储区域之后的下一个地址。或者 0。
指向常量的指针(pointer to const): 是一个指针,存放着某个常量对象的地址。指向常量的指针不能用来改变它所指对象的值。
预处理器(preprocessor): 在 C++编译过程中执行的一段程序。
预处理变量(preprocessor variable): 由预处理器管理的变量。在程序编译之前,预处理器负责将程序中的预处理量替换成它的真实值。
引用(reference): 某个对象的别名。
对常量的引用(reference to const): 是一个引用,不能用来改变它所绑定对象的值。对常量的引用可以绑定常量对象,或者非常量对象,或者表达式的结果。
作用域(scope): 是程序的一部分,在其中某些名字有意义。C++由几级作用域。
全局(global): 名字定义在所有其他作用域之外。
类(class): 名字定义在类内部。
命名空间(namespace): 名字定义在命名空间内部。
块(block): 名字定义在块内部。名字从声明位置开始直至声明语句所在的作用域末端为止都是可用的。
分离式编译(separate compilation): 把程序分割为多个单独文件的能力。
带符号类型(signed): 保存正数,负数或 0 的整型。
字符串(string):是一种库类型,表示可变长字符序列。
struct 是一个关键字,用于定义类。
临时值(temporary): 编译器在计算表达式结果时创建了一个临时值,则此临时值将一直存在直到包含该表达式的最大的表达式计算计算完成。
顶层 cosnt(top-level const): 是一个 const,规定某对象的值不能改变。
类型别名(type alias): 是一个名字,是另外一个类型的同义词,通过关键字 typedef 或别名声明语句来定义。
类型检查(type checking): 是一个过程,编译器检查程序使用某给定类型对象的方式与该类型的定义是否一致。
类型说明符(type specifier): 类型的名字。
typedef: 为某类型定义一个别名。当前关键字 typedef 作为声明的基本类型出现时,声明中定义的名字就是类型名。
未定义(undefined): 即 C++语言没有明确规定的情况。不论是否有意为之,未定义行为可能引发难以跟踪的运行时错误,安全问题和可移植性问题。
未初始化(uninitialized): 变量已定义但未赋予初始值。一般来说,试图访问未初始化变量的值将引发未定义行为。
无符号类型(unsigned): 保存大于等于 0 的整型。
变量(variable): 命名的对象或引用。C++语言要求变量要先声明后使用。
void* : 可以指向任意非常量的指针类型,不能指向解引用操作。
void 类型: 是一种有特殊用处的类型,既无操作也无值。不能定义一个 void 类型的变量。
字(word): 在指定及其上进行整数运算的自然单位。一般来说,字的空间足够存放地址。32 位机器上的字通常占据 4 个字节。
& 运算符(& operator): 取地址运算符。
* 运算符(* operator): 解引用运算符。解引用一个指针将返回该指针所指的对象,为解引用的结果赋值也就是为指针所指的对象赋值。
#define: 是一条预处理指令,用于定义一个预处理变量。
#endif: 是一条预处理指令,用于结束一个 #ifdef 或 #ifndef 区域。
#ifdef: 是一台预处理指令,用于判断给定的变量是否已经定义。
#ifndef: 是一条预处理指令,用于判断给定的变量是否尚未定义。