基本类型
wchar_t长度为16bit,用来存储拓展长度的字符;char16_t与char32_t用来存储16bit与32bit长度的Unicode编码。char类型与signed char类型不同。在使用
char类型时,必须要规定它是signed char还是unsigned char。不能只用char。如果要用到比
int大的数字,则使用long long来表示,因为int一般与long的长度相等。在使用内置数据类型(例如
string或者vector<T>)时,使用string::size_type及vector<T>::size_type来表示相应数据类型的大小。- 好处是不会溢出。
- 内部实现是使用
typedef常用数据类型。
类型转换
- 如果将一个溢出值赋予给一个有符号类型,结果将会报错。
- 有符号数与无符号数相加,有符号数以无符号数读取(如果为负数则读取出错误的值)
立即数(Literals)
- 正常书写的数字为int型。20==024==0x14
- 可以通过给立即数增加前缀或后缀来确定一个立即数的类型。
小数默认为double型

string是char型的列表,并在末尾增加了\0。但是strlen()返回的仍然是不加\0的个数。
变量
- 在函数中,新定义的内建类型是没有初始化的。这种情况下不能访问它。
- 初始化类对象时,由类来决定初始的值。但是尽量手动初始化所有内建类型的变量。
- 使用
extern可以声明但不定义变量。(extern int i;)
C++ 关键字

- 系统保留的标识符(Identifier)包括连续两个下划线、下划线后接大写字母、函数外定义的变量不能由下划线开头。
命名习惯
- 变量名通常是小写字母。
- 类名通常是大写字母开头。
- 变量名由多个单词组成的时候用下划线分隔。
作用域
- 在任何括号之外的域为全局的。
- 为了更高可读性,应该在第一次使用的时候定义变量,而不是在开头定义。
- 在变量
a为全局变量的情况下,某个代码块中还可以声明局部变量a。- 代码块内,在声明局部变量之前,访问的
a是全局变量。 - 声明局部变量之后,访问
a则为局部变量。 - 声明局部变量之后,可以使用
::a来访问全局变量,全局标识符没有名字,所以留空。
- 代码块内,在声明局部变量之前,访问的
复合类型
引用
- 声明一个引用时必须初始化。
- 在绑定了一个变量的引用之后,不能再绑定别的变量。
- 引用不是对象,而是一个对象的另一个名称。
- 一个变量可以有多个引用。
指针
- 指针指向其他类型的变量。
- 声明null指针,以下三个等价:
int *p1 = nullptrint *p1 = NULLint *p1 = 0
- 不能用整型等变量类型给指针的地址赋值。
void*是指向了一个具体的地址,但是没有定义类型,因此它可以指向各种类型的对象。
const修饰词
- const在创建的时候必须初始化,并且之后不能改变。
- 在使用立即数对const变量进行赋值时,会直接将变量名变为立即数。
- 要想在多个源文件中只创建一个const,则需要用
extern来定义。 - 如果用
const指针或引用对一个普通变量进行操作,那么它们无法改变这个变量。 const reference是const变量的引用,但可以引用int等变量。const分为高级与低级int *const p1 = &i;等价于constexpr int *q = nullptr高级:指针本身是const的const int *p2 = const int c1 = 2;低级:指针指向的变量是const的。
constexpr修饰词
- 在初始化一个const类型时,有时不确定初始化的表达式是否为常量,则可以用
constexpr来限定初始化表达式必须为常量。目的是为了让编译器检查赋值语句等号右边的变量是const的。 const类型可以用变量来进行初始化。
变量类型操作
类型别名
typedef double wages;表示可以使用wages代替double。using SI = Sales_item;表示可以用SI表示“Sales_item类型”。typedef char *pstring;意思是pstring表示char*。
auto
- 使用
auto必须初始化变量,其类型由初始化表达式决定。 - 在对auto类型变量进行初始化时,有时会与原类型不同
- 使用引用类型进行初始化时,此变量会被初始化成被引用的变量类型。而引用可以这样写
auto &g = x; - auto会忽略top-level的
const而保留low-level的const。而top-level的变量可以这样写const auto f = x;
- 使用引用类型进行初始化时,此变量会被初始化成被引用的变量类型。而引用可以这样写
decltype类型
如果我们需要提取一个表达式的类型,而不需要一个表达式的具体值的时候,可以使用decltype。
decltype(f()) sum = x;是基本的使用方法。这里编译器只会判断函数f的返回值,而不执行f。decltype可以根据初始化时的类型,来对被初始化的变量类型进行调整。
- 如果一个变量不加任何括号,则使用变量内容的类型;如果一个变量加括号,则将这个变量当做一个表达式,使用这个表达式本身的类型。

自定义数据结构
结构体
建议用下面第一种方式定义结构体变量,下面两种方式等价。 注意结构体后面的分号!
// method 1
struct Sales_data {
/*....*/
} accum, trans, *salesptr;
// method 2
struct Sales_data {
/*....*/
};
Sales_data accum, trans, *salesptr;
自定义头文件
预处理程序从C继承,在编译之前运行,用来替换源代码中的头文件等内容。为了防止一个头文件被多次包含,预处理程序定义了header guards来根据预处理程序变量来判断。预处理程序变量包含两个状态:定义和没定义。
#define命令后面跟一个名称,作为一个预处理变量。
#ifdef返回真表示已经被定义过。#ifndef返回真表示还没被定义过。- 如果上面的命令返回真,则顺序执行,直到
#endif。
正常的栗子如下:
#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
- 预处理变量名不遵守作用域规则。所以变量名必须在整个程序中是独一无二的。在习惯上我们通常将它全部大写。
- 在实际项目中,强烈推荐每个头文件都带有
header guards,即使只有一个头文件。
static的局部变量
对于一个函数里面的static局部变量,变量存储在代码段。非static的局部变量存储在堆栈段。
下图是带
static变量的结果int func_test_static(int init){ if(init > 0){ static int temp = 9; for(int i=0;i<init;i++){ temp += i; } return temp; } return 0; }
下图是不带
static变量的结果
int func_test(int init){
if(init > 0){
int temp = 0;
for(int i=0;i<init;i++){
temp += i;
}
return temp;
}
return 0;
}

- 下图是使用
new操作符存放变量的结果
int func_test_new(int init){
if(init > 0){
int* temp = new int;
for(int i=0;i<init;i++){
(*temp) += i;
}
return *temp;
}
return 0;
}
