引用和指针的区别,*和&操作符

来源:互联网 发布:网络最火的歌2017 编辑:程序博客网 时间:2024/05/16 05:34

一、在声明中见到这两个操作符(*和&)时:

在程序声明变量的时候使用的*,只是表明“它是一个整数,这个整数为某个内存地址,一次访问sizeof(type)长度”。这点不要和(*)操作符混淆;

在程序声明变量的时候使用的&,只是表明“它是一个引用,这个引用声明时不开辟新空间,它在内存分配表加入新的一行,该行内存地址等于和调用时传入的对应参数内存地址”。 这点不要和(*)声明符,(&)操作符混淆。

引用:(&)

引用就是某一变量(目标)的一个别名,对引用的操作与对变量直接操作完全一样。

引用的声明方法:类型标识符 &引用名=目标变量名;

【例1】:int a; int &ra=a; //定义引用ra,它是变量a的引用,即别名

  说明:

  (1)&;在此不是求地址运算,而是起标识作用。

  (2)类型标识符是指目标变量的类型。

  (3)声明引用时,必须同时对其进行初始化

  (4)引用声明完毕后,相当于目标变量名有两个名称,即该目标原名称和引用名,且不能再把该引用名作为其他变量名的别名

                                            ra=1; 等价于 a=1;

  (5)声明一个引用,不是新定义了一个变量,它只表示该引用名是目标变量名的一个别名,它本身不是一种数据类型,因此引用本身不占存储单元,系统也不给引用分配存储单元。故:对引用求地址,就是对目标变量求地址。&ra与&a相等。

  (6)可以建立数组的引用。int m[10]={1,2,3,4,5,6,7,8,9,10}; int (&n)[10]=m; 

        (7)不能建立引用的引用,不能建立指向引用的指针。因为引用不是一种数据类型,所以没有引用的引用,没有引用的指针。

              例如:

       int n;

       int &&r=n;//错误,编译系统把"int &"看成一体——引用,把"&r"看成一体——引用,即建立了引用的引用,引用的对象应当是某种数据类型的变量

       int &*p=n; //错误,编译系统把"int &"看成一体——引用,把" *p "看成一体——指针,即建立了指向引用的指针,指针只能指向某种数据类型的变量

        (8)值得一提的是,可以建立指针的引用

          例如:

            int *p;

            int *&q=p;//正确,编译系统把" int * "看成一体——指针,把"&q"看成一体——引用,即建立指针p的引用,亦即给指针p起别名q。

引用与指针的区别:

          使用引用(reference)和指针(pointer)都可以间接访问另一个值,但它们之间存在两个重要区别:

         1.引用总是指向某个确定对象(事实上,引用就是该对象的别名),定义引用时没有进行初始化会出现编译错误;

         2.赋值行为上存在差异:  给引用赋值修改的是该引用所关联的对象的值,而不是使该引用与另一个对象关联.引用一经初始化,就始终指向同一个特定对象.

                                                   给指针赋值修改的是指针本身,也就是使该指针指向另一对象,指针在不同时刻可指向不同的对象

例:

int ival=1024,ival2=2048;
int *pi=&ival, *pi2=&ival2; //pi指向ival,pi2指向ival2
pi=pi2; //pi此时所指与pi2相同了,即指向ival2了

该赋值操作仅修改了指针pi的值,而pi开始所指向的ival对象值保持不变

对比:

int &ri=ival,&ri2=ival2;
ri=ri2; //assigns ival2 to ival

该赋值操作修改了引用-ri的对象-ival的值,ival的值变成了ival2了,而引用两个本身不变,都还是分别指向原来所关联的对象

 

 

二、在声明中见到这两个操作符(*和&)时:

(一)生成左值的解引用操作(*)——得到所指对象

string s("hello world");
string *sp=&s; //sp 指向s,sp的值是s的地址;sp是一个整数,这个整数指向某个内存地址即s的地址,一次访问sizeof(string)长度

修改指针所指对象的值:    *sp="goodbye"; 即此时s的改变了,因为进行了解引用操作(*操作),

修改指针的值:1.string s2="some value";
                              sp=&s2; //即此时sp 指向s2,而不是s了,sp自身改变了,因为没有使用解引用操作

                            2.string s2("some value");
                               string *sp2=&s2; //sp2指向s2

                               sp=sp2; //此时sp也指向s2了,值变成了s2的地址,同样没有使用解引用操作

区分的重要方法是:   如果对左操作数进行解引用,则修改的是指针所指对象的值;

                                   如果没有使用解引用操作,则修改的是指针本身的值.

(二)取址符(&)——得到自身的地址

我们假设有这么两段内存地址空间,他们取值如下:(单位:H,16 进制)

(假设开辟空间时p 被分配给了3001H、3002H 两个位置)

        int *p;

  p=2003H; //则p指向了2003H处,值为30 00

  *p=3000H //p所指向的对象的值变为3000H

  ----------------------------------------------------

1.**p的值为多少?

  **p=*(*(p))=*(*(2003H))=*(3000H)=0300H。

        故**p即为3000H所指向的对象,值为03 00

2.&&p的值为多少?

      &&p=&(&(p))=&(3001H),&p为获得p的地址即我们前面假设的3001H。再对3001H取址,此时出错了,

      3001H 是个常数怎么可能有地址呢? !!!

3.*&p的值为多少?

    *&p=*(&(p))=*(3001H)=2003H,也就是*&p=p。//*(3001H)得到3001H所指对象即20 03——注意,它得到的不是自身哦,有变化

4.&*p的值为多少?

    &*p=&(*(p))=&(3000H),读者可能以为&*p=p, 此时出错了,同样的3000H 是个常数怎么可能有地址呢?

原创粉丝点击