随笔-145  评论-173  文章-70  trackbacks-0

C++的引用和指针

 

 

1.     C++的引用。

关于C++的引用,需要有很多的注意的地方。

首先,引用的对象必须是实际存在的。而不能使不存在的对象。例如 int && a = i;这个就是不对的,为何,因为引用的是一个引用,而实际上引用时不存在的,不是一个实体,而只是一个别名,所以违反了该条规则。不成立。

其次,看看下面的这个代码:int i = 12; int &a = i; int &b = a;

看看这个,我们想想,有没有问题呢?初看之下,觉得有些问题,因为ai的引用,没问题,OK。但是ba的引用啊,也就是说b是一个引用的引用,这个怎么能行呢,引用不是实体嘛,所以不行。然而你自己动手试试,发现代码不仅能够正常运行,而且值都是12,仔细分析。我们应该知道个大概。前面的两句没有任何问题,至于后面,我们慢慢来看。int &b = a;程序执行到这里的时候,我们都知道a是一个引用,那么针对a的任何操作,都是实际作用到它引用的对象的,也就是说,这里面是一个赋值,把a引用的对象赋值给b的引用,也就是说b是一个引用,引用哪个对象呢?就是a引用的对象。我们在使用引用的时候,一定要记得,任何对该引用的操作,实际上都要作用到它引用的对象,如果是a++,那么也是相当于i++,而不要认为是针对a的,像这种情况比较明显,可是上面的那个例子,我认为还是相当有迷惑性的,至少我开始的时候被迷惑了,所以说,实践是检验真理的唯一标准嘛。通过分析,进一步了解到关于引用操作的本质,这个才是我们的目的。

下面来谈谈几个复杂一点的引用:

1.     const引用和非const引用。Const引用指的是指向const对象的引用,说明该引用的对象是一个常量,所以,任何对该引用的赋值都是错误的,任何对引用的操作都会替换为对所引用变量的操作,于是就是对一个const赋值,所以错误。如何正确的识别呢?一个简单的例子入手。

const  int &f = 12;这里是正确的吗?当然,因为这里就是const引用,所以引用的对象是12的时候是正确的。如何识别,很简单,将&*看做都是一个和类型结合的新类型,那么就是(const int) & f,那么f的类型就是前面的修饰,所以就是说它首先是引用(据C++ Primer一书介绍从右往左读的办法),然后const修饰该引用的对象,就像是下面的这个int &p,修饰的就是说p引用的对象是int,也就是说,返回类型是int的就表示引用指向的是int,同样,char &p则表示引用p引用的是一个字符变量,那么这里,就是说f引用的是一个(const int)类型的变量,所以说,它引用的是一个常量。对于非const引用,说明引用的变量时可以改变的,那么就是普通的形式:   int &p = a;这样的话,就可以对其进行赋值来改变a的值了。还要注意的一点的是,对于const类型的变量,需要在定义的时候初始化,因为const变量时不允许再次赋值,改变的,所以如果你不在初始化的时候赋值,那么后面就不能够初始化,而只会认为是赋值,造成错误。

下面来看看两种特殊的情况。1const int ival = 1024;  int &p = ival; 错误,为何,因为p是非const引用,说明可以通过p来修改引用的对象,可是它引用的对象却是一个const类型的变量,所以矛盾,是错误的。

2)const int &p = 1024;   正确,为何,因为const引用就是只读引用,所以不会修改常量1024,没有任何问题。

3)int &p = 1024;  错误,同1)中的问题,如果是非const引用,是可以修改的。

 

2.     复杂的const声明和类型举例:(s[] = {1,2,3};)

int (&a)[3] = s;  //正确的,而且a就是数组s的引用,可以认为a就是s的别名,那么可以这样输出s的各个成员:a[0],a[1],a[2],这样的话,通过赋值也是可以修改s的内容的。关键是如何理解这个式子的含义,首先括号优先级较高,所以声明a肯定是一个引用,而外面的话是 一个数组,数组的类型可以通过前面的类型限定符int来说明,这样,a就是一个引用,引用的是一个整型数组。

int &a[3] = s; //错误的,因为数组时要分配空间的,而引用时不占用空间的,所以引用不能够作为数组的成员。如何看待呢?首先看a是一个数组,而该数组的类型是int&,说明每一个存放的内容都是引用,明显不对。理由已述。

附注:从这里可以得到复杂数组的判断,就说对于一个数组A s[],那么就说明数组的每一个元素都是A类型的,所以,以后碰到类类型的数组,标准库类型的数组,就不用绞尽脑汁的思考了。前面的类型,就说明了改数组的存放元素的类型。

 

3.     引用到底占用空间吗?

#include <iostream>

using namespace std;

class A

{

         int p;

         int *m;

         int &a;

         static int t;

public:

         int *print(){}

};

int main()

{

         cout << sizeof(A) << endl;

}

为何此处的输出结果是12呢?难道说引用还是占用了空间?如果不是,结果不可能是这么多的~~~

 

 

4.     int &y = ++++i; //i的初始值为0的话,这里y引用的值是多少?y还是引用i吗?

是的,为何?因为++++i是一个左值表达式,所以需要先计算出来它的值,而它的值就是2,而且返回值就是i,注意执行这个运算之后,返回值是i,而且i的值已经发生了变化,那么剩下的就是int &y = i;但是此处的i是一个变化后的i,它的值是2,所以说y还是引用i,要看清楚结果和返回值就不会迷惑了………

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

2.     C++中的指向常量的指针和常量指针。

1.指向常量的指针:const char *str = “str”;表示的是什么呢?str是一个指针,指向的是一个字符串常量”str”,所以说,str指向的对象是不能够变的,也就是说,凡是*str = “”这样的赋值,就是一种错误,因为不能够再次改变常量的值。而str本身不是常量,所以就是说,str是可以变的。那么,现在我可以这么做。str = “new string”,这样的话,str指向的是一个新的对象,而不是原来的那个const对象。如何好好的理解呢?可以从右往左看,*表示str是一个指针,而指针的返回值是const char ,所以就是说,str是一个指针,指向的是一个字符串常量。我们可以这样来理解。              int t = 23;   int *p= &t;  这里p的类型也是一个指针,就是说,返回值int *,也就是说返回值是一个指向整形的指针。所以返回是const char的时候,也就是指向的是const char类型对象的。

2.常量指针。何谓常量指针,就是指针本身是一个常量,也就是说指针本身的值不能够改变,而指针是一个地址,所以说该地址是不能够改变的。于是,就不能够对它进行再次赋值,就是说指针的值不能再改变了。定义形式如下:  char *const p ;这里从右往左看看,发现p是一个指针,而用const来修饰它的,所以就是说此指针是不能够改变的。而返回值,char *说明就是说返回值是指针了,那么此句就分析到这里.

char *const p = “hello,world”,那么*p = “new string”就是对的了,因为这个改变的是指针p所指向的对象,而不是本身p的值,也就是说指针本身是没有变的,满足常量指针的定义。但是,如果p = “new”;那么就是一个错误。而*p指的对象是可以改变的。

3.     输入输出的问题。

#include <iostream>

using namespace std;

 

int main()

{

const char *p = "const";

cout << *p << endl;

p = "hello";

cout << p << endl;

char t[12] = "djife";

cout << t << endl;

return 0;

}

结果是:

c

hello

djife

注意输出的时候,为何有的是字符串,有的时候一个字符,那么为何出现这种情况呢?看看这个输出格式,一个是*p,而一个p,那么就是形式不同,一个*p表示的是以p的地址作为解引用,那么现在这样的结果就是表示的第一个字符,所以输出的就是c,而p是指针,所以输出一个指针的直接结果就是一个字符串,注意到是字符串数组,所以用指针的话输出就是一个字符串。

posted on 2009-12-27 18:47 deercoder 阅读(324) 评论(0)  编辑 收藏 引用 所属分类: C/C++

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理