重温C++——变量和基本类型

基本内置类型

类型 含义 最小尺寸
bool 布尔 未定义
char 字符 8位
wchar_t 宽字符 16位
char16_t Unicode字符 16位
char32_t Unicode字符 16位
short 短整型 16位
int 整型 16位
long 长整型 32位
long long 长整型 64位
float 单精度浮点数 6位有效数字
double 双精度浮点数 10位有效数字
long double 扩展精度浮点数 10位有效数字

复合类型

引用

  引用(reference)为对象起了另外一个名字,引用类型引用(refers to)另外一种类型,通过将声明符写成&d的形式来定义引用类型,其中d是声明的变量:

int ival = 1024;
int& refVal = ival;	//refVal是ival的另一个名字
int& refVal2;		//错误,引用类型必须初始化

一般在初始化变量时,初始值会被拷贝到新建的对象中。然而定义引用时,程序把引用和它的初始值绑定(bind)在一起,而不是将初始值拷贝给引用。一旦初始化完成,引用将和它的初始值对象一直绑定在一起。因为无法令引用重新绑定到另外一个对象,因为引用必须初始化。
  引用只是为一个已经存在的对象另外取了一个名字。

指针

  指针(pointer)是指向(point to)另外一种类型的复合类型。与引用类似,指针也实现了对其他对象的间接访问。然而指针与引用相比有有很多不同点。其一,指针本身就是一个对象,允许对指针赋值和拷贝,而且在指针的生命周期内它可以先后指向几个不同的对象。其二,指针无须在定义时赋初值。和其它内置类型一样,在块作用域内定义的指针如果没有被初始化,也将拥有一个不确定的值。
  定义指针类型的方法将声明符写成*d的形式,其中d是变量名:

int* p = NULL;	//也可以使用0

复合类型的声明

  变量定义包括一个基本的数据类型(base type)和一组声明符。在同一行的定义域居中,虽然基本数据类型只有一个,但是声明符的形式却可以不同。也就是说,一条定义语句可能定义出不同类型的变量:

//i是一个int类型,p是一个int指针,r是一个int型的引用
int i = 1024, *p = &i, &r = i;

  经常有一种观点误以为,类型修饰符(*和&)作用于本行定义的全部变量。造成这种错误看法的原因有很多,其中之一是我们可以把空格写在类型修饰符和变量名中间:

int* p = NULL;

  感觉int*可以修饰这条语句中的所有变量,其实恰恰相反,基本数据类型是int,而不是int*。*仅仅修饰了p而已,对该声明语句中的其它变量,它并不产生任何作用:

int* p1, p2;	//p1是int类型的指针,p2是int

  涉及指针或者引用的声明,一般那有两种写法。第一种把修饰符和变量标识符写在一起,这种形式强调变量具有复合类型:

int *p1, *p2;	//p1和p2都是指向int的指针

  另一种形式把修饰符和类型名写在一起,并且每条语句只定义一个变量,这种形式着重强调本次声明定义了一种复合类型:

int* p1;
int* p2;

  我喜欢第二种写法!!!

指向指针的指针

  一般来说,声明符中修饰符的个数并没有限制。当有多个修饰符连写在一起时,按照逻辑关系解释即可。以指针为例,指针是内存中的对象,像其它对象一样有自己的地址,因此允许把指针的地址放到一个一个指针中,通过*的个数可以区分指针的级别:

int ival = 1024;
int* pi = &ival;	//pi指向int
int** ppi = π	//ppi指向int类型的指针

引用指针的引用

  引用本身不是一个对象,因此不能定义指向引用的指针。但指针是对象,所以可以有指针的引用:

int i = 42;
int* p = NULL;	//p是指针
int*& r = p;	//r是指针p的引用
r = &i;			//r即p, 相当于p = &i

const修饰符

const和引用

  可以把引用绑定到const对象上,就像绑定到其它对象一样,称为对常量的引用(reference to const)。与普通引用不同的是,对常量的引用不能用来修改它所绑定的对象:

const int ci = 1024;
const int& r1 = ci;
r1 = 42;			//错误,r1所引用的对象是常量
int& r2 = ci;		//错误,非常量引用不能绑定到常量对象上

  经常把“对const的引用”简称为“常量引用”,这不是说引用是常量(因为不能更改引用所绑定的对象,在这个层面上所有的引用都是常量),而是说不能通过引用去改变所绑定的对象。为了对ci进行引用,r1必须有const修饰符,否则就像和r2一样了。const type&这种形式主要使用在函数传参中。
  下面的代码也是合法的:

int i = 42;
int& r1 = i;
const int& r2 = i;
r1 = 0;
r2 = 0;				//错误

  这里r2同样有const修饰符,所以不能通过r2改变i

const和指针

指向常量的指针

  和引用一样,也可以让指针指向常量或非常量。类似于常量引用,不能通过指向常量的指针(pointer to const)来改变指针所指向的对象。要想存放常量对象的地址,只能使用指向常量的指针:

const double pi = 3.14;
double* ptr = π			//错误,pi是个常量,普通(非常量)指针不能指向常量
const double* cptr = π
*cpter = 42;
double dval = 3.14;
*cptr = &dval;

  类似引用,因为piconst修饰,所以cptr必须有const修饰,否则就和ptr一样,可以通过指针来修改pi的值了。指向常量的指针也可以指向非常量:

double dval = 3.14;
const double* cptr = &dval;

常量指针

  因为指针是对象,所以可以把指针定义为const的,即常量指针(const pointer),表示指针本身是常量。这种类型的指针必须初始化,而且一旦初始化完成,它的值(即存放在指针中的地址)就不能再改变了。把*放在const之前说明指针是一个常量,这样的写法表示指针本身的值不变而不是指针所指向的值不变:

int errNumb = 0;
int* const curErr = &errNumb;	//写成int*的形式更容易理解,表示curErr是指针类型的常量
const double pi = 3.14;
const double* const pip = π

  int*的形式表示curErr是指针类型的,const表示它是常量,既然是某种类型的常量,那就不能修改,所以不能修改curErr的值,它将一直指向errNumb
  同样的,pipconst double*类型的,第二个const表示pip是常量,所以pip是指向双精度浮点类型常量的常量指针。第二个const表示pip不能被修改,第一个const表示pip指向的值不能被修改。

顶层const

  顶层const(top-level const)表示对象本身是常量,底层const(low-level const)表示所指向和引用的对象是常量,指针类型既可以是顶层const,也可以是底层const:

int i = 0;
int* const p1 = &i;			//p1是顶层const,不能改变p1的值
const int ci = 42;			//ci是顶层const,不能改变ci的值
const int* p2 = &ci;		//p2是底层const,可以改变p2的值,但是不能通过p2修改所指向的对象
const int* const p3 = p2;	//靠右的是顶层const,靠左的是底层const
const int& r = ci;			//引用的const都是底层const
i = ci;						//顶层const不影响拷贝
p2 = p3;					//同上
int* p = p3;				//错误,p3具有底层const,而p没有
p2 = &i;					//int*可以转换为const int*
int& r = ci;				//错误,int&不能引用const int
const int& r2 = i;			//const int&可以绑定到const 上

实例分析

  以const int* const& r为例,r为对指向常量的指针的常量引用。
  这种复杂的复合类型一般采用从右往左的方式进行解读:
    &r表明r是一个引用;
    const& r表明不能通过r修改所引用的对象;
    * const& r表明r是所引用的对象是一个指针;
    int* const& r表明指针指向int类型;
    const int* const& r表明r所引用的对象指向的是常量整型;
  第二个const表示r是对常量的引用,即不能通过r改变所引用的对象,第一个const表示指针所指向的对象是常量,即不能通过r来改变所指向的对象。简单来说r是一个指针,第二个const是顶层的,表示不能通过r来改变指针的值,即r++是错误的;第一个const是底层的,表示不能通过r来改变指针所指向的值,*r = 0是错误的。

猜你喜欢

转载自blog.csdn.net/RayoNicks/article/details/83016728