引用、指针和const

来源:互联网 发布:sql server 教程 高级 编辑:程序博客网 时间:2024/05/22 03:28
本文是学习《c++ primer》第五版第二章的学习笔记。有更新会再补充。

声明语句:基本数据类型+声明符

复合类型

引用(reference)

  1. int ival = 10;
  2. int &refVal = ival; // & 是引用标识符

  • 必须初始化

  1. int &refVal2 ; // 错误,未初始化

定义引用时,程序把引用和其初始值绑定(bind)在一起,而不是将初始值拷贝给引用。
  • 引用不是对象,而是给已有对象起了另外一个名字。
  • bind:现在引用和初始值绑定在了一起,就像是一条绳上的蚂蚱福祸相依,不管是引用和变量谁发生了改变,另一个都会随之改变。

  •  引用的类型必须与其所引用对象的类型一致。有两个例外:
引用的例外一:初始化常量引用时允许用任意表达式作为初始值,只要该表达式的结果能转换成引用的类型即可。
  1. int i = 42; 
  2. int &r1 = i;  
  3. const int &r2 = i; //r2是常量引用,绑定对象i(非常量),意思是不允许通过r2修改 i 的值
  4. r1 = 0; // 正确,i的值修改为0,由于r2和i绑定在一起,r2也变为0;i的值也可以通过其他途径修改,r2也会跟着发生变化
  5. r2 = 0; //错误,r2是一个非常量引用

指针(pointer)

  1. int*ip1,*ip2;//允许没有初始化,此处 * 是声明的一部分
  2. int ival=42*p=&ival; //p存放变量ival的地址,或者说p是指向变量ival的指针;此处 & 是取地址符
  3. cout<<*p;// 此处 * 是解引用符,输出指针p指向的对象
  • 利用指针访问对象
如果指针指向了一个对象,则可以使用解引用符(操作符 * )来访问该对象。

  • 指针的值(即地址),要属于下列4种状态之一:
  1. 指向一个对象;
  2. 指向紧邻对象所占空间的下一个位置;
  3. 空指针,意味着指针没有指向任何对象;
  4. 无效指针,是上述三种情况的其他值。

  • 所有指针的类型必须和其所指向的对象严格匹配。有两个例外:
指针的例外一:允许令一个指向常量的指针指向一个非常量对象。
  1. double dval = 3.14;
  2. const double *cptr = &dval;//正确,但是不能通过cptr改变dval的值,dval自身可以通过其他途径改变



  • 生成空指针的几种方法:

  1. int *p1 = nullptr; //C++程序最好使用该方法
  2. int *p2 = 0;
  3. int *p3 = NULL; // 使用该方法需要先 #include cstdlib ,尽量避免使用NULL
  • void* 指针可以存放任意对象的地址,我们对该对象是什么类型并不事先了解。

  • 其他指针操作:
  1. 用在表达式中;
    1. int *pi = 0;
    2. if (pi) //条件等价于false
    3. //...

  2. 用相等操作符(==)或不等操作符(!=)比较指针,比较的内容是指针存放的地址,结果是布尔类型。


引用VS指针

 是对象吗?生命周期要初始化吗?和const   引用不是一旦初始化完成,无法将引用重新绑定到另外一个对象要!对常量的引用,也称为“常量引用”。
限制的是引用可以执行的操作(不能对其赋值),而不是引用的对象(引用的对象不一定是常量)   指针是,允许赋值和拷贝可以先后指向不同的对象不是必须,但建议初始化。
因为块作用域内的指针如果未初始化,将拥有一个不确定的值指向常量的指针:指针的对象是常量
限制情况和对常量的引用类似,不能通过指针改变该对象,但是对象自己可以通过其他途径改变常量指针:指针是常量。
必须初始化!   

复合类型的声明

指向指针的指针

通过 * 的个数可以区分指针的级别。
  1. int ival = 42
  2. int *pi = &ival;
  3. int **pi = &pi;

指向指针的引用

要理解一个变量的类型到底是什么,最简单的方法就是从右向左阅读该变量的定义。距离变量名最的符号对变量的类型有最直接的影响。
  1. int i = 42;
  2. int *p;
  3. int *&r = p; // 此处离 r 最近的符号是 & ,因此r 是一个引用,*说明r 引用的是一个指针
  4. r = &i;
  5. *r = 0;

const限定符

  • 必须初始化,因为const对象一旦创建后就不可再更改
  • 默认const对象仅在文件内有效,如果想在多个文件之间共享const对象必须在变量的定义前添加 extern 关键字。
  • 只能在const对象上执行不改变其内容的操作。

const的引用(reference to const)

  • 称为:对常量的引用(reference to const),简称“常量引用”,(二者是一个概念)但实际上不存在恒定不变的引用,这只是一个称呼。(主要是和“常量指针”对比。)
  • 可以这么理解,对常量的引用十分讲究“门当户对”。引用的对象是常量(const对象),那么引用前也要有const;反之,如果引用定义为对常量的引用,就不能使其指向一个非常量对象。如下所示:
  1. const int ci = 42; 
  2. const int &r1 = ci;//正确,引用及其对象都是常量
  3. r1 = 42;    //错误,r1是对常量的引用,不能对其赋值
  4. int &r2 = ci; //错误,ci是一个常量,而引用r2没有加const限定符,就不能引用一个常量。
  • 常量引用仅对引用可参与的操作做出了限定,对于引用的对象本身是不是一个常量未作限定,对const的引用可能引用一个并非const的对象,见上:#引用的例外一

指向常量的指针(pointer to const)

  1. const double pi = 3.14;
  2. double *ptr = &pi; //错误,ptr不是一个常量指针,而试图指向一个常量,不够“门当户对”
  3. const double *cptr = &pi; //正确
  4. *cptr = 42; //错误,指向常量的指针不能再被赋值

  • 可以令一个指向常量的指针指向一个非常量对象,这是:#指针的例外一

常量指针(const pointer)

  • 常量指针必须初始化,且初始化完成以后将不再改变,一直指向指针中存放的地址。
  • 将*放在const前面,就表明这个指针是一个const。
  1. int errNumb = 0;
  2. int *const curErr = &errNumb; //curErr将一直指向errNunb
  3. const double pi = 3.14;
  4. const double *const pip = &pi; //pip是一个指向常量对象的常量指针

顶层const

指针本身是不是常量和指针的对象是不是常量,是两个相互独立的问题,用顶层const (top-level const)表示指针本身是一个常量,用底层const (low-level const)表示指针所指的对象是一个常量。


















0 0
原创粉丝点击