C++Primer 变量和基本类型
还是从最基础的来看吧,简单的大概看一下吧。
char是8位类型,最多只能包含256种字符,许多外文字符集所含的字符数目超过256个,char型无法表示。如中文字符,就可用 wchar_t来表示
Unicode是国际组织制定的可以容纳世界上所有文字和符号的字符编码方案。能够使计算机实现跨语言、跨平台的文本转换及处理。
void* 指针
可用于存放任意对象的地址
作用:拿它与其他类型的指针比较、作为函数的输入或输出、赋给另一个void*指针
不能直接操作void*指向的对象
指向指针的引用
引用本身不是一个对象,因此不能定义指向引用的指针,但是指针是对象,存在对指针的引用
r到底是什么?
最简单的方法是从右向左阅读r的定义。离变量最近的符号对变量的类型个有最直接的影响。
所以,在此例中,r是一个引用。r引用的是一个int指针。
const与指针中,用名词顶层const 表示指针本身是个常量,而用底层const表示指针所指的对象是一个常量。
constexpr和常量表达式
常量表达式——值不会改变并且在编译过程中就能得到计算结果的表达式。用常量表达式初始化的const对象也是常量表达式。
constexpr变量
允许将变量声明为constexpr类型以便由编译器来验证变量的值是否是一个常量表达式。声明为constexpr的变量一定是一个常量,而且必须用常量表达式初始化:
Tips:一般来说,如果你认定变量是一个常量表达式,那就把它声明成constexpr类型。
字面值类型
常量表达式的值需要在编译时就得到计算,因此对声明constexpr时用到的类型必须有所限制。
这些类型称为“字面值类型”。
算数类型、引用和指针 属于字面值类型。
自定义类、IO库、string类型则不属于字面值类型。也就不能定义成constexpr。
PS:一个constexpr指针的初始值必须是nullptr或者0,或者是存储于某个固定地址中的对象。
一般来说,定义于所有函数体之外的对象其地址固定不变,允许函数定义一类有效范围超过函数本身的变量,这类变量和定义在函数之外的变量一样也有固定地址。因此,constexpr引用能绑定到这样的变量上,constexpr指针也能指向这样的变量。
constexpr指针中,限定符constexpr仅对指针有效,与指针所指的对象无关。
constexpr把它所定义的对象置为了顶层指针
指针、常量和类型别名
不能简单的将类型别名替换成它本来的样子,以理解该语句的含义:
如 const char *cstr = 0; //理解错误!!!
用到pstring时,其基本数据类型是阵阵,声明了一个指向char的常量指针
改写后,数据类型变成了char,*成了声明符的一部分,声明了一个指向const char 的指针。
auto声明 让编译器判断数据类型,一般会忽略掉顶层const,同时底层const则会保留下来
设置一个类型为auto的引用时,初始值中的顶层常量仍然保留。和往常一样,如果我们给初始值绑定一个引用,则此时的常量就不是顶层常量了。
PS:要在一条语句中定义多个变量,切记!符号*和&只从属于某个声明符,而非基本数据类型的一部分,因此初始值必须是同一类型。
decltype类型指示符
选择并返回操作数的数据类型
declttype(f()) sum = f() //sum的类型就是表达式f()的类型
const int ci = 0, &cj = ci; decltype(ci) x = 0; decltype(cj) y = x; //y的类型是const int&, y 绑定到变量x decltype(cj) z; //错误:z是一个引用,必须初始化
decltype和引用
//decltype的结果可以是引用类型 int i = 42, *p = &i, &r = i; decltype(r + 0) b; //正确:加法的结果是int,因此b是一个(未初始化的)int decltype(*p) c; //错误:c是int&,必须初始化
解引用指针可以得到指针所指的对象,而且还能给这个对象赋值。因此,decltype(*p)的结果类型就是int&,而非int
使用decltype时,如果变量名加上了一对括号,则得到的类型与不加括号时会有不同。不加括号,得到的结果是该变量的类型,如果给变量加上了一层或多层括号,编译器就会把它当成一个表达式。变量是一种可以作为赋值语句左值得特殊表达式,所以这样的decltype就会得到引用类型:
decltype((i)) d; //错误:d是int&,必须初始化 decltype(i) e; //正确:e是一个(未初始化de)int