引用和指针的那些事

2.3.1 引用

引用并非对象,相反的,它只是为一个已存在对象所起的另外一个名字。
示例:
int ival = 1024;
int &refVal = ival;

Tips:
1.除2种情况外,引用的类型要和与之绑定的对象严格匹配

2.引用必须被初始化,且一旦初始化后,它和初始值对象一直绑定在一起,不能更改绑定的对象

3.引用本身不是一个对象,所以不能定义引用的引用

2.3.2 指针
取地址符(操作符&), 解引用符(操作符*)
示例:
int ival = 42;
int *p = &ival;

指针的4种状态:
a. 指向一个对象
b.指向相邻对象所占空间的下一个位置
c. 空指针,指针没有指向任何对象
d. 无效指针,就是上述情况外的其他值

如果指针指向了一个对象,则允许使用解引用符*来访问该对象(解引用,仅用于有指定对象的有效指针):
如上例操作对象,直接用 *P。

空指针的3种生成方式:
a. int *p1 = nullptr; (C++11新引入,推荐使用)

b. int *p2 = 0;

c. int *p3 = NULL;

Tips:
1.除2种情况外,指针的类型要和它指定的对象严格匹配。

2.建议初始化所有指针。

3.赋值操作时,永远改变的是等号左侧的对象。
int *pi = 0;
pi = &ival; //pi的值被改变,现在pi指向了ival
*pi = 0; //ivald的值发生改变

4.将指针作为if语句的判断条件时,指针值为0,则为false;指针值非0,则为true。

5.void*指针可用于存放任意对象的地址,其内存空间仅仅是内存空间,没法访问内存空间所存的对象,
所以void* 指针能做的事比较有限: 拿它和别的指针比较;作为函数的输入或输出,或者赋值给另外一个void*指针

补充(理解复合类型的声明:):
1.
int* p1,p2; //p1是指向int的指针,p2是int型整数
int *p1,*p2; //p1和p2都是指向int的指针

2.指向指针的指针:
通过*的个数可以区分指针的级别,如**表示指向指针的指针。***表示指向指针的指针的指针。,如:
int ival = 1024;
int *pi = &ival; //pi指向一个int型的数(ival)
int **pi = π //ppi指向一个int型指针(pi)

3.面对比较复杂的指针或者引用的声明语句时,从右向左阅读有助于弄清它的真实含义。如:
int i =42;
int *p; //p是一个int型的指针
int *&r = p; //r是一个对指针p的引用

r = &i;
*r=0;

第三行,要理解r的类型到底是什么,从右到左阅读r的定义。离变量名r最近的符号(此例是&r符号的&)对变量的类型最直接的影响,
因此r是一个引用,声明符的其他部分用来确定r引用的类型是什么(此例中的符号*,说明r引用是一个指针)

2.4 const限定符

  1. const对象一旦创建后其值就不能再改变,所以const对象必须初始化。

               

  2. 默认情况下,const对象仅在文件内有效。若想在多个文件中声明并使用它,需要添加关键字extern:

                                //file_1.cc

                                extern const int bufSize = fcn();

                                //file_1.hh头文件,与cc中定义的bufSize是同一个

                                extern const int bufSize;

3.1-Const的引用(常量引用):
const int ci =1024;
const int &r1 = ci; //正确,引用及其对应的对象都是常量

Tips:
a. 允许为一个常量引用绑定一个非常量的对象、字面值,甚至是个一般表达式:
int i = 42;
int &r1 = i;
const int &r2 = i; //正确,允许将const int&绑定到一个普通的int 类型
const int &r3 = 42; //正确
r1 = 0; //正确
r2 = 0; //错误,r2是一个常量引用

补充: 常量引用对于引用的对象本身是不是常量未作限定,仅对引用可参与的操作做出了限定

b. 一个常量引用被绑定到另外一种类型上:
double dval = 3.14;
const int &r1 = dval; //r1会绑定到由dval临时生成的int型临时量(对象)

3.2-指针和const:
与引用一样,想要存放常量对象的地址,只能使用指向常量的指针
const double pi = 3.14;
const double *cptr = π //cptr可以指向一个双精度常量

const指针:
常量指针必须初始化。而且一旦初始化则它的值就不能再改变了。
把*放在const关键字之前用以说明是一个常量,也意味着不变的是指针本身的值而非指向的那个值。(从右向左读)
int errNumb = 0;
int *const currErr = &errNumb; //currErr将一直指向errNumb
const double pi = 3.14;
const double *const pip = π //pip是一个指向常量对象的常量指针

3.3-顶层const:

指针:
顶层const:表示指针本身是一个常量
底层const:表示指针所指的对象是一个常量

int i =0;
int *const p1 = &i; //顶层const
const int ci = 42; //顶层const,不能改变ci的值
const int *p2 = &ci; //底层const
const int *const p3 = p2; //右边的是顶层const,左边的是底层const
const int &r = ci; //用于声明的const都是底层const

执行对象的拷贝操作时,顶层const不受什么影响。但是,拷入和拷出的对象必须具有相同的底层const资格。
或者两个对象的数据类型必须能相互转换,一般来说,非常量可以转换为常量,反之则不行。
int *p = p3; //错误:p3包含底层const的定义,而p没有
p2 = p3; //正确:p2和p3都是底层const
p2 = &i; //正确:int*能转换成const int*(指的是i)
int &r = ci; //错误:普通的int& 不能绑定到int常量上
const int &r2 = i; //正确:const int& 可以绑定到一个普通int上

3.4 constexpr和常量表达式
后续补充

二、处理类型


原文地址:https://www.cnblogs.com/tsinghuama/p/9930540.html