C++的引用和指针
1. C++的引用。
关于C++的引用,需要有很多的注意的地方。
首先,引用的对象必须是实际存在的。而不能使不存在的对象。例如 int && a = i;这个就是不对的,为何,因为引用的是一个引用,而实际上引用时不存在的,不是一个实体,而只是一个别名,所以违反了该条规则。不成立。
其次,看看下面的这个代码:int i = 12; int &a = i; int &b = a;
看看这个,我们想想,有没有问题呢?初看之下,觉得有些问题,因为a是i的引用,没问题,OK。但是b是a的引用啊,也就是说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变量时不允许再次赋值,改变的,所以如果你不在初始化的时候赋值,那么后面就不能够初始化,而只会认为是赋值,造成错误。
下面来看看两种特殊的情况。1)const 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;
}
|
结果是:
注意输出的时候,为何有的是字符串,有的时候一个字符,那么为何出现这种情况呢?看看这个输出格式,一个是*p,而一个p,那么就是形式不同,一个*p表示的是以p的地址作为解引用,那么现在这样的结果就是表示的第一个字符,所以输出的就是c,而p是指针,所以输出一个指针的直接结果就是一个字符串,注意到是字符串数组,所以用指针的话输出就是一个字符串。
posted on 2009-12-27 18:47
deercoder 阅读(340)
评论(0) 编辑 收藏 引用 所属分类:
C/C++