[C++编程笔记] 01 变量和数据类型
联系作者:359152155@qq.com
文章目录
C++数据类型总图
- 内置类型
- 基本内置类型
- 算数类型:布尔型、字符型、整型、浮点型
- 空类型(void)
- 引用
- 指针
- 数组
- 基本内置类型
- 自定义类型
- struct
- class
- enum
1. 算数类型
1.1
类型 | 含义 | 最小尺寸 |
---|---|---|
bool | 未定义 | |
char | 字符 | 8位 |
wchar_t | 宽字符 | 16位 |
char16_t | Unicode字符 | 16位 |
char32_t | Unicode字符 | 32位 |
short | 16 位 | |
int | 32位 | |
long | 32位 | |
long long | 64位 | |
float | 32位 | |
double | 64位 |
带符号和无符号
- short、int、long、long long都是带符号的,加上前缀unsigned就可以得到无符号类型。
- char是否带符号由编译器决定。signed char专用来指定带符号char,unsigned char专用来指定无符号char。
关于符号的注意事项:
- 算数运算时切勿混用带符号类型和无符号类型。如果表达式里既有带符号类型又有无符号类型,当带符号类型取值为负时会出现异常结果。例:
如果有
int a = -1; unsigned int b = 1;
,则表达式a*b
的值并非-1。结果具体是什么由当前机器上int所占位数而定。 - 算数表达式中不要使用char或bool。因为char类型是否带符号由编译器决定。如果你确实需要一个不大的整数,明确指定他的类型是signed char或unsigned char。
1.2 算数类型字面量
整型字面量的类型
默认情况下,十进制字面量是带符号数,类型是能容纳其数值的int、long、long long中最小者。八进制和十六进制字面量的类型是能容纳其数值的int、unsigned int、long、unsigned long、long long、unsigned long long中的最小者。
整型字面量后缀
- u或U:表示unsigned
- l或L:表示至少是long
- ll或LL:表示至少是long long
- 无后缀:表示至少是int
浮点型字面量后缀
- f或F:表示float
- l或L:表示long double
- 无后缀:表示double
字符型字面量前缀
- u:表示Unicode 16字符,类型char16_t。例:
u'a'
。 - U:表示Unicode 32字符,类型char32_t。例:
U'a'
。 - L:表示宽字符,类型wchar_t。例:
L'a'
。 - 无前缀:类型char。
2. 指针和引用类型
2.1 引用类型
引用为对象起了一个别名。例:
int a = 1024;
int &refA = a; // 引用refA是对象a的别名
定义引用时,必须初始化,使引用与其初始值绑定到一起。
一旦初始化完成,引用将和它的初始值对象一直绑定在一起。
2.2 指针
int *p1, *p2;
int a = 45;
int *p = &a;
空指针: nullptr
。
void *
指针
void *
指针是一种特殊的指针类型,可以存放任意对象的地址。
多级指针
int **a;
int ***b;
指针的引用
int a = 45;
int *pa = &a;
int *&refPA = pa; // refPA是对指针对象pa的引用。即:refPA是pa的别名。
2.3 const限定符
const限定符限制变量的值在初始化之后就不能改变。
2.3.1 定义const变量
const int a = 512;
小提示
默认状态下,const对象仅在文件内有效。当多个文件中出现了同名的const变量时,其实等同于在不同的文件中分别定义了独立的变量。
如果需要在一个文件中定义const变量,而在其他多个文件中声明并使用它。可以在const变量的定义和声明都加上extern关键字:
// file1.cc 定义并初始化了一个const变量
extern const int bufSize = 45;
// file1.h 声明该const变量
extern const int bufSize;
2.3.2 const的引用
对常量的引用(reference to const)。例:
const int ci = 1024;
const int &refCI = ci;
const的引用也可以绑定到一个临时对象。所谓临时对象,就是当编译器需要一个空间来暂存表达式求实结果时,临时创建的一个未命名对象。例:
int a = 40;
const int &r1 = a*5; // 表达式a*5的结果作为一个临时量绑定到r1上。
double b = 1.25;
const int &r2 = b; // 相当于:const int temp = b; const int &r2 = temp;
const的引用可以引用一个并非const的对象
const的引用仅对引用可参与的操作做出了限定,对于引用的对象本身是不是一个常量未作限定。
int i = 42;
int &r1 = i;
const int &r2 = i; // r2也绑定了i,但是不允许通过r2修改i。
2.3.3 const与指针
指向常量的指针
const int a = 45;
const int *cpa = &a;
指向常量的指针也没有规定其所指的对象必须是一个常量。所谓指向常量的指针仅仅导致不能通过该指针改变对象的值。例:
int a = 45;
const int *cpa = &a;
*cpa = 46; // 错误
a = 46; // 正确
const指针
指针本身是常量。例:
int a = 0;
int *const pa = &a; // pa将一直指向a,不能变更地址,但可以通过pa修改对象的值。
const int b = 1;
const int *const pb = &b; // pb是一个指向常量对象的常量指针
2.3.4 顶层const和底层const
名词 顶层const 表示对象是个常量。
名词 底层const 表示指针所指的对象是一个常量。
举例:
int i = 0;
int *const p1 = &i; // 这是一个顶层const,不能改变p1中的地址。
const int ci = 42; // 这是一个顶层const,不能改变ci中的值。
const int *p2 = &ci; // 这是一个底层const,不能改变p2指向的对象的值,允许改变p2中的地址。
const int *const p3 = p2; // 右边的const是顶层const,它限定p3中的地址不可改变。靠左的const是顶层const,它限定不能修改p3指向的对象的值。
const int &r = ci; // 用于声明引用的const都是底层const。
当执行对象的拷贝操作时,拷入和拷出的对象必须满足:具有相同的底层const
,或底层非const
转换为const
。而顶层const
并不是拷贝能否进行的条件。
3. 其他与类型有关的事情
3.1 定义类型别名
传统的方式(C风格的)
typedef double Width; // Width是double的同义词
typedef Width Abc, *p; // Abc是double的同义词,p是double *的同义词
新标准引入的方式
using UI = UserInfo; // UI是UserInfo的同义词
3.2 auto类型说明符
C++11引入了auto
类型说明符,用它可以让编译器替我们去分析表达式所属的类型。
// 编译器根据a + b的结果的类型推断出item的类型
auto item = a + b;
关于auto
有两点注意:
- 若表达式的结果是引用类型,auto会去掉表达式结果类型中的引用。例:
int i = 0; int &r = i; auto a = r; // a将会是int型,而不是int&型。
- auto一般会去掉表达式结果类型中的顶层const,但底层const一定会保留下来。
int i = 0; const int ci = i; const int &cr = ci; auto a = ci; // a是int型(顶层const被丢弃) auto b = cr; // b是int型(cr是ci的别名,而ci是const int型,顶层const将被丢弃) const int *cpi = &i; const int *const cpci = &i; auto c = &i; // c是int*型 auto d = cpi; // d是const int*型(底层const被保留) auto e = cpci; // e是const int*型(顶层const被丢弃, 底层const被保留) auto f = &ci; // f是const int* (对常量对象取地址是一种底层const)
那么问题来了:
- 如果希望推断出的auto类型含有引用,怎么搞? 方法是使用
auto &
:int i = 0; auto &g = i; // g是int& const int ci = i; auto &h = ci; // h是const int& (注意,此时的顶层const被保留了)
- 如果希望推断出的auto类型是一个顶层const,怎么搞? 方法是使用
const auto
:const int ci = i; const auto x = ci; // x推断出来是const int类型