c笔记再论引用二_第1页
c笔记再论引用二_第2页
c笔记再论引用二_第3页
c笔记再论引用二_第4页
全文预览已结束

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、.试着反驳先看下面一个例子:#include using namespatd;class Testprivate:char a=a; char &b=a;/C+11 已经允许这么干了main()coutsizeof(class Test)endl;return 0;结果为 8 。怎么解释这一?若依所述,则结果应该为 1 才对。这么会是 8 呢?在此,先给出的另一定义:是一个指向不可变的、被编译器自动解的指针,即,是一个被编译器自动解的指针常量。关于以上定义,先给出以下几点说明:“指向不可变”是说,指针 p 指向a 后就不能再指向 b 或其它,但 a 的值是可以改变的(a在 const 下的情况

2、除外),如 a 原来为 3,可以改为 5。这与先前的认识:“c 既为a 的a=3;)”相符。就不能为 b 的,但 a=5;和 c=5;都可以(假定原来正确区分“常量指针”与“指针常量”。常量指针是指向常量的指针,也可以指向变量,无法用*操作,但可以改变指向。指针常量是说该指针具有常量的性质,其指向不能改变,但其指向的内容不一定是不可改变的。(正如所述)3.关于“自动解”,下边会详述。根据以上定义,表达式 char &b=a;将被编译器转化成 char* const b=&a;基于以上定义,来解释 8 这一结果:a 为 char 型,占 1 个字节,b 实质上为指针,有自己的内存空间,占 4 个

3、字节,所以,一共占 5 个字节。而结果为 5 不为 8 的原因是内存对齐的缘故。(关于内存对齐,这里不详述,有解)由此可见,“不占用内存”并不是那么准确。关于是否占用内存问题,下面的说法似乎更折中一些:C+标准规定,可以占内存也可以不占内存,具体怎么样取决于编译器的实现。其中占内存的实现就是使用指针,就如方法。上边谈到的那样。很多编译器为了简单都采用这种不占用内存的情况是:和被的对象在同一函数中(指在函数体中,不包括形基址的偏移量,在这种情况下,定义该局部变量的参)。局部变量名实际上是一个相对,编译器可以直接给这个赋同样的偏移值(这里不分配内存,名和偏移值存在于符号表中),这样名和变量名完全没

4、有区别。这种情况下,别名就名副其实了。但是,回过头来想,和被的对象出现在同一函数中的情况并不多见,同时也想不出这样做作为函数参数时,确实只有指针这一种实现方式了。意义。同时,再看下面这段代码: #include using namespatd;main()i=10;&j=i; j+;coutiendljendl; cout&iendl&jendl;return0;结果:11110 x28fef8 0 x28fef8如果说前两行结果可以用&j=i; * j=&i;来解释,那么,后两行结果似乎要中的定义转而支持中的结论了。前边有过“自动解”一说,所谓“自动解”,就是编译器自动将 j 转化为*j(注

5、意j 是指针),所以 coutj 转化为 cout*j,即 couti; cout&j 转化为 cout&*j 转化为cout&i,所以,输出的就是 i 的地址。这里的关键是,编译器将&j=i; cout&j;转化成了* j=&i; cout&*j;。多说一句,当 p 是指针时,&*p *&p p。代码段a=3;* p=&a; cout&*pendl*&pendlpendl;可以编译通过且三个输出结果相同。前面已经,&*p &a p,对于*&p,&p 就是取得 p 的地址(注意 p 是*型指针,自然也是变量,它本身也得有空间,也得有地址,这里不妨将&p 记作 pp),知道,*p 就是取得 p

6、所指变量(a)的内容(3),所以,*pp 就是取得 pp 所指变量(p)的内容(a 的地址,即&a)这里红色的 p 是变量名,其余的 p 都是变量 p 的内容,即 a 的地址通过以上叙述,不难发现,中对的定义更能解释已有现象。另外,基于&j=i; * j=&i;及“自动解”,不难分析以下代码:#include #includeusing namespatd;main()a=1;& b=a; & c=b; & d=c;c+;couta,b,c,dendl; return 0;结果:2,2,2,2以上代码被编译器处理为:& b=a; const& c=b; const & d=c; const*

7、b=&a;* c=&*b;(自动解* d=&*c; d=c;,b *b)c=bc+; *c+; a+;(a 变为 2)couta,b,c,dendl; coutabcd(为方便,这里把”,”和 endl 忽略掉)coutabbb couta*b*b*b coutaaaa下面再来说一说的初始化。“时必须同时将其初始化”,说的没错,因为 const 类型变量必须在的同时初始化(在 main 函数中,const a;无法编译通过)。但还应该注意到, & a=10;无法编译通过但 const& a=10;却可以。这里涉及到非常量(不带 const 的)与常量结论再稍加解释。若一个表达式或变量是(必须带

8、 const 的),及与右值。还是先说,则可以用来初始化非常量(当然也可以初始化常量引用);如为右值,则只能初始化常量。换句话说,对于右值,只能用常量来)。关于常量,后边还会详述,这里先简说与右值(欲知关于左、右值,貌似没有明确的定义,但有判别方法:可以取地址的是,反之是右值。当然,可以放在=左边的是,反之是右值,也可以粗略地判断。下面说一个较为典型的,其它的可以#include 。在以下代码中,using namespatd;main()a=1;& b=(+a); cout&(+a)endl;/& c=(a+);/cout&(a+)endl;return 0;注释掉的两句是不能编译通过的。也就是说,+a 是,而 a+是右值。+a 是先自增,然后返回自增后的变量 a(正如若 d=+a;则d 为 2),a 是变量,本来就可以做;a+是后自增,其实现方法是先拷贝一份 a(这份拷贝的值仍为 1),然后使 a 增加 1,最后返回那份拷贝(正如若 d=a+;则d 为 1 而不是 2),而那份拷贝是临时对象,临时对象不可以对其取地址,是右值,且是 const 型的,所以非常量不可以而常量可以(const&c=(a+);可以编译通过)。相对临时对象而言,这里 a 为持久对象。(关于临时对象,后边还

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论