指针和引用中一些要注意的问题

引用

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

int ival=1024;

int &refval=ival;   //refval指向ival(是ival的另一个名字)

int &refval2;     //报错:引用必须初始化

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

引用即别名

引用并非对象,相反的,它只是为一个已经存在的对象所起的另外一个名字。

定义一个引用之后,对其进行的所有操作都是在与之绑定的对象上进行的:

refval=2;//把2赋给refval指向的对象,此处即是赋给了ival

int li=refval; //与li=ival执行结果一样

为引用赋值,实际上是把值赋给了与引用绑定的对象。获取引用的值,实际上是获取了与引用绑定的对象的值。同理,以引用作为初始值,实际上是以与引用绑定的对象作为初始值:

//正确:refval3绑定到了那个与refval绑定的对象上,这里就是绑定到了ival上

int &refval3=refval;

//利用与refval绑定的对象的值初始化变量i

int i=refval;  //正确: i被初始化为ival的值

因为引用本身不是一个对象,所以不能定义引用的引用。

使用引用要注意的两点:

1 一般的,引用类型要和与之绑定的对象严格匹配。

2 引用只能绑定在对象上,而不能与字面值或某个表达式的计算结果绑定在一起。

指针

指针是指向另一种类型的复合类型。与引用类似,指针也实现了对其它对象的间接访问。然而指针与引用相比又有很多不同点。其一,指针本身就是一个对象,允许对指针赋值和拷贝,而且在指针的声明周期内它可以先后指向几个不同的对象。其二,指针无须在定义时赋初值。和其他内置类型一样,在块作用域内定义的指针如果没有被初始化,它将拥有一个不确定的值。

指针值

指针的值(即地址)应属于下列4中状态之一:

1 指向一个对象

2 指向紧邻对象所占空间的下一个位置

3 空指针,意味着指针没有指向任何对象

4 无效指针,也就是上述情况之外的其他值

利用指针访问对象

如果指针指向了一个对象,则允许使用解引用符(操作法*)来访问该对象。

解引用操作符仅适合用于那些确实指向了某个对象的有效指针。

空指针

空指针不指向任何对象,在试图使用一个指针之前代码可以首先检查他是否为空。以下列出几个生成空指针的方法:

int *p1=nullptr;   //等价于int *p1=0;

int *p2=0;    //直接将p2初始化为字面常量0

//需要首先#include cstdlib

int *p3=NULL;  //等价于int *p3=0;

得到空指针最直接的方法就是用字面值nullptr来初始化指针,这是C++11新标准刚刚引入的一种方法。nullptr是一种特殊类型的字面值,它可以被转换成任意其他的指针类型。另一种方法就如对p2的定义一样,也可以通过将指针初始化为字面值0来生成空指针。

赋值和指针

指针和引用都能提供对其他对象的间接访问,然而在具体实现细节上二者有很大不同,其中最重要的一点就是引用本身并非一个对象。一旦定义了引用,就无法令其再绑定到另外的对象,之后每次使用这个引用都是访问它最初绑定的那个对象。

指针和它存放的地址之间就没有这种限制了。和其他任何变量(只要不是引用)一样,给指针赋值就是令他存放一个新的地址,从而指向一个新的对象。

有时候要想搞清楚一条赋值语句到底是改变了指针的值还是改变了指针所指的对象的值不太容易,最好的办法就是记住赋值永远改变的是等号左侧的对象。当写出如下语句时,

pi=&ival; //pi的值被改变,现在pi指向了ival

意思是为pi赋一个新的值,也就是改变了那个存放在pi内的地址值。相反的,如果写出如下语句:

*pi=0;  //ival的值被改变,指针pi并没有改变

则*pi(也就是指针pi指向的那个对象)发生改变。

指向指针的指针

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

通常*的个数可以区分指针的级别。也就是说,**表示指向指针的指针,***表示指向指针的指针的指针,以此类推:

int ival=1024;

int *pi=&ival;    //pi指向一个int型的数

int **ppi=π   //ppi指向一个int型的指针

此处pi是指向int型数的指针,而ppi是指向int型指针的指针。

解引用int型指针会得到一个int型的数,同样,解引用指向指针的指针会得到一个指针。此时为了访问最原始的那个对象,需要对指针的指针做两次解引用。

指向指针的引用

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

int i=42;

int *p; //p是一个int型的指针

int *&r=p; //r是一个对指针p的引用

r=&i;  //r引用了一个指针,因此给r赋值&i 就是令p指向i

*r=0; //解引用r得到i,也就是p指向的对象,将i的值改为0

要理解r的类型到底是什么,最简单的办法是从右向左阅读r的定义。离变量名最近的符号(此例中是&r的符号&)对变量的类型有最直接的影响。因此r是一个引用。声明符的其余部分用以确定r引用的类型是什么,此例中的符号*说明r引用的是一个指针。最后,声明的基本数据类型部分指出r引用的是一个int指针。

面对一条比较复杂的指针或引用的声明语句时,从右向左阅读有助于弄清楚它的真实含义。

指针和引用中一些要注意的问题

时间: 2024-10-03 22:30:14

指针和引用中一些要注意的问题的相关文章

浅谈C++中指针和引用的区别

指针和引用在C++中很常用,但是对于它们之间的区别很多初学者都不是太熟悉,下面来谈谈他们2者之间的区别和用法. 1.指针和引用的定义和性质区别: (1)指针:指针是一个变量,只不过这个变量存储的是一个地址,指向内存的一个存储单元:而引用跟原来的变量实质上是同一个东西,只不过是原变量的一个别名而已.如: int a=1;int *p=&a; int a=1;int &b=a; 上面定义了一个整形变量和一个指针变量p,该指针变量指向a的存储单元,即p的值是a存储单元的地址. 而下面2句定义了一

转 浅谈C++中指针和引用的区别

浅谈C++中指针和引用的区别 浅谈C++中指针和引用的区别 指针和引用在C++中很常用,但是对于它们之间的区别很多初学者都不是太熟悉,下面来谈谈他们2者之间的区别和用法. 1.指针和引用的定义和性质区别: (1)指针:指针是一个变量,只不过这个变量存储的是一个地址,指向内存的一个存储单元:而引用跟原来的变量实质上是同一个东西,只不过是原变量的一个别名而已.如: int a=1;int *p=&a; int a=1;int &b=a; 上面定义了一个整形变量和一个指针变量p,该指针变量指向a

C++ 浅谈C++中指针和引用

浅谈C++中指针和引用的区别 指针和引用在C++中很常用,但是对于它们之间的区别很多初学者都不是太熟悉,下面来谈谈他们2者之间的区别和用法. 1.指针和引用的定义和性质区别: (1)指针:指针是一个变量,只不过这个变量存储的是一个地址,指向内存的一个存储单元:而引用跟原来的变量实质上是同一个东西,只不过是原变量的一个别名而已.如: int a=1;int *p=&a; int a=1;int &b=a; 上面定义了一个整形变量和一个指针变量p,该指针变量指向a的存储单元,即p的值是a存储单

C++中指针和引用的区别

此文转自:http://www.cnblogs.com/kingln/articles/1129114.html 从概念上讲.指针从本质上讲就是存放变量地址的一个变量,在逻辑上是独立的,它可以被改变,包括其所指向的地址的改变和其指向的地址中所存放的数据的改变. 而引用是一个别名,它在逻辑上不是独立的,它的存在具有依附性,所以引用必须在一开始就被初始化,而且其引用的对象在其整个生命周期中是不能被改变的(自始至终只能依附于同一个变量). 在C++中,指针和引用经常用于函数的参数传递,然而,指针传递参

C++ 中指针与引用的区别

指向不同类型的指针的区别在于指针类型可以知道编译器解释某个特定地址(指针指向的地址)中的内存内容及大小,而void*指针则只表示一个内存地址,编译器不能通过该指针所指向对象的类型和大小,因此想要通过void*指针操作对象必须进行类型转化.     ★ 相同点: 1. 都是地址的概念: 指针指向一块内存,它的内容是所指内存的地址: 引用是某块内存的别名.     ★ 区别: 1. 指针是一个实体,而引用仅是个别名: 2. 引用使用时无需解引用(*),指针需要解引用: 3. 引用只能在定义时被初始化

以指针和引用两种参数实现删除单链表L中所有值为X的结点的函数

下面是单链表的数据结构 typedef struct LNode{ ElemType data; struct LNode *next; }LNode,*Linklist; 1.以指针参数实现 void delete_x_1(LNode *head,ElemType x){//head为单链表头结点,删除结点的值为x LNode *l = head; LNode *p = head->next; while(p != null){ if(p->data == x){ l->next =

为什么C++类定义中,数据成员不能被指定为自身类型,但可以是指向自身类型的指针或引用?为什么在类体内可以定义将静态成员声明为其所属类的类型呢 ?

static的成员变量,不是存储在Bar实例之中的,因而不会有递归定义的问题. 类声明: class Screen: //Screen类的声明 1 类定义: class Screen{ //Screen类的定义 //etc... }; 1 2 3 当用实例化一个类的对象时,编译器会根据类的定义来分配相应的存储空间.也就是说,在创建对象前,一定要有完整的类定义,这样编译器才能正确的计算所需空间. 那么我们来看如下代码: class Screen{ Screen sc; //error, 'sc'

向函数中传递指针和传递指针的引用的区别

如果是传递指针,那么会先复制该指针,在函数内部使用的是复制后的指针,这个指针与原来的指针指向相同的地址,如果在函数内部将复制后的指针指向了另外的新的对象,那么不会影响原有的指针:但 是对于传递指针应用,如果将传递进来的指针指向了新的对象,那么原始的指针也就指向了新的对象,这样就会造成内存泄漏,因为原来指针指向的地方已经不能再 引用了,即使没有将传递进来的指针指向新的对象,而是在函数结束的时候释放了指针,那么在函数外部就不能再使用原有的指针了,因为原来的内存已经被释放了 看个例子: #includ

指针的引用——在函数中的巧妙应用

前面有一篇文章讲了指针与引用.并且还提到不能定义指向引用的指针(因为引用不是对象,没有实际的地址).那么,能否定义指针的引用呢?答案是肯定的,因为指针本身就是一个对象.即然是对象,就能定义一个引用邦定该对象.先来看看指针的引用的用法: 以int类型为例如下: void ReferencePointer() { int i = 5; // 变量i int* p = &i; // 指针p,指向变量i int*& pr = p; // 指针的引用,与p指向同一个变量i cout <<