第I部分 C++基础
第2章 变量和基本类型
2.1.1 算术类型
2.1.2 类型转换
1. 当给无符号类型的变量赋值时,如果超出表示范围,结果是初始值对无符号类型表示数值总数去模后的余数,例如,8比特大小的unsigned char可以表示0至255区间内的值,如果赋一个超出该范围的值,则实际的结果是该值对256取模后所得的余数。
2. 赋带符号类型一个超出它表示范围的值时,结果是未定义的。
3. 如果表达式中既有符号类型又有无符号类型,则符号类型数将自动转换成无符号类型数。
unsigned u=10;
int i=-42;
std::cout<<u+i<<std::endl; //如果int占32位,输出4294967264
2.2.1 变量定义
1. 列表初始化:对内置类型的变量,如果使用列表初始化且初始值存在丢失信息的风险,则编译器将报错
long double ld=3.1415926536;
int a{ld},b={ld}; //错误
int c(ld),d=ld; //正确
2. 定义于任何函数体外的变量被默认初始化为0,定义于函数体内的内置类型的对象如果没有显式初始化,则其值未定义。
3. 变量只能被定义一次,但可以声明多次,任何包含了显式初始化的声明即成为定义。
2.2.3 标识符
- 用户自定义的标识符中不能连续出现两个下划线,也不能以下划线紧连大写字母开头。此外,定义在函数体外的标识符不能以下划线开头。
2.3 复合类型
2.3.1 引用
- 左值:可以放在赋值符号左边的变量;右值:当一个符号或者常量放在操作符右边;
- 引用必须被初始化,一旦初始化完成,引用将和它的初始值对象一直绑定在一起;
- 引用本身不是对象,所以不能定义引用的引用;
- 所有引用的类型必须与之绑定的对象严格匹配;
int &refVal1=10; //错误:初始值必须是一个对象
double dval=3.14;
int &refVal2=dval; //错误:类型不匹配
2.3.2 指针
- 指针本身就是一个对象;
- 不能把int变量直接赋值给指针;
int zero=0;
int *pi;
pi=zero; //错误
3. void*是一种特殊的指针类型,可以用于存放任意对象的地址。
4. void*指针能做的事有:拿它与其他指针比较、作为函数的输入或输出、赋值给其他void*指针,但是不能直接操作void*指针所指的对象。
2.3.3 理解复合类型的声明
int* p1,p2; //p1是指向int的指针,p2是int
int *p;
int *&r=p //r是一个对指针p的引用
- 对于比较复杂的指针或引用的声明语句,可以从右向左阅读有助于弄清其真实的含义;
2.4 const限定符
- 文件之间共享const变量时,对于const变量不管是声明还是定义都添加extern关键字,这样只需定义一次就可以了。
- 在初始化常量引用时允许用任意表达式作为初始值,只要改表达式的结果能转换成引用的类型即可。
- 对const的引用可能引用一个并非const的对象。反之则不行。
int i=42;
const int &r=i; //r绑定对象i,但是不允许通过r修改i的值
4. 顶层const表示指针本身是一个常量,而底层const表示指针所指对象是一个常量。
5. 和常量引用一样,指向常量的指针可以指向一个非常量,但指向非常量的指针不能指向一个常量
6. 常量表达式是指值不会改变并且在编译过程就能得到计算结果的表达式,constexpr变量一定是一个常量并且必须用常量表达式初始化。
7. 在constexpr声明中如果定义一个指针,限定符constexpr仅对指针有效,与指针所指的对象无关。
const int *p=nullptr; //p是一个指向整型常量的指针
constexpr int *q=nullptr; //q是一个指向整数的常量指针
2.5.1 类型别名
- typedef
typedef double wages; //wages是double的同义词
typedef wages base,*p; //base是double的同义词,p是double*的同义词
2. using
using SI=Sales_item; //SI是Sales_item的同义词
3. 指针、常量和类型别名
typedef char *pstr;
const pstr cstr=0; //cstr是指向char的常量指针
const pstr *ps; //ps是一个指针,它的对象是指向char的常量指针
const char *cstr1=0; //对const pstr cstr的错误理解
2.5.2 auto类型说明符
- auto让编译器通过初始值来推算变量的类型,显然,auto定义的变量必须有初始值,一条声明语句中所有变量的初始基本数据类型都必须一样。
auto i=0,pi=3.14; //错误:i和pi的类型不一致
2. 使用引用作为初始值时,以引用对象的类型作为auto的类型。
int i=0,&r=i;
auto a=r; //a是一个整数
3. auto一般会忽略掉顶层const,同时底层const则会保留下来。
const int ci=i, &cr=ci;
auto b=ci; //b是整数(ci的顶层const被忽略)
auto c=cr; //c是整数(cr是ci的别名,ci本身是一个顶层const)
auto d=&i; //d是整型指针(整数的地址就是指向整数的指针)
auto e=&ci; //e是指向整数常量的指针(对常量对象取地址是一种底层const)
2.5.3 decltype类型指示符
- decltype的作用是选择并返回操作数的数据类型。
const int ci=0, &cj=ci;
decltype(ci) x=0; //x的类型是const int
decltype(cj) y=x; //y的类型是const int&,y绑定到变量x
decltype(cj) z; //错误:z是一个引用,必须初始化
2. 如果表达式的内容是解引用操作,则decltype将得到引用类型。
int i=42,*p=&i;
decltype(*p) c; //错误:c是int&,必须初始化
3. 对于decltype所用的表达式来说,如果变量名加上一对括号,则得到的类型与不加括号时会不同。
decltype((i)) d; //错误:d是int&,必须初始化
4. decltype((variable))的结果永远是引用。