引用的作用

2016-01-29 12:27 9 1 收藏

引用的作用,引用的作用

【 tulaoshi.com - C语言心得技巧 】

引用的作用

作者: panic
2005年3月27日

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com)

  众所周知,引用作为函数参数可以避免参数对象的额外拷贝,对于非内置类型,一般而言可以获得更高的效率,同时比指针更安全,语义也更清晰。但是除此之外引用有什么特别的作用呢?在同一个作用域的引用,就像这样:

void f(){ int i = 0; int &ri = i; //这里。 //...}

  事实上,在f的内部,需要操作i的地方,完全可以直接使用i,而不必要使用ri间接操作,使用i在语义上更明确。而混合使用i和ri反倒容易引起逻辑的混乱。

似乎这是一个鸡肋,但是其实不是。

这里引用乾坤一笑文章中的例子:
例一、用C宏,书写代码更简洁
这段代码写网络程序的朋友都很眼熟,是Net/3中mbuf的实现。

struct mbuf{ struct m_hdr mhdr; union {  struct  { struct pkthdr MH_pkthdr; /* M_PKTHDR set */ union  {  struct m_ext MH_ext; /* M_EXT set */  char MH_databuf[MHLEN]; } MH_dat;} MH;char M_databuf[MLEN]; /* !M_PKTHER, !M_EXT*/} M_dat;};

  上面的代码,假如我想访问最里层的MH_databuf,那么我必须写M_dat.MH.MH_dat.MH_databuf; 这是不是很长,很难写呀?这样的代码阅读起来也不明了。其实,对于MH_pkthdr、MH_ext、MH_databuf来说,虽然不是在一个结构层次上,但是如果我们站在mbuf之外来看,它们都是mbuf的属性,完全可以压扁到一个平面上去看。所以,源码中有这么一组宏:

#define m_next m_hdr.mh_next#define m_len m_hdr.mh_len#define m_data m_hdr.mh_data... ...#define m_pkthdr M_dat.MH.MH_pkthdr#define m_pktdat M_dat.MH.MH_dat.MH_databuf... ...

这样写起代码来,是不是很精练呢!

  这里用宏很巧妙的解决了访问深层数据的问题,但是宏的固有缺点也被引入了代码中,同时,如果其他地方无意中引用了这个宏定义的头文件,而且恰好使用了名为m_pktdat的数据成员,那这个宏带来的后果可就不是我们想要的了。
  事实上用引用也可以达到类似的效果,不过必须是在使用的时候。由于引用不是标准C的组成部分,所以这只是一个C++技巧。

//假如代码是这样的:mbuf m; //这里的mbuf就是前面的struct mbuf。//如果要使用MH_ext成员,可以这样:m_ext &MH_ext = m.M_dat.MH.MH_dat.MH_ext;//然后你的代码中就可以直接使用MH_ext作为m.M_dat.MH.MH_dat.MH_ext的替代品了。

  也许看起来不是很自然,不过这无疑是一种很直接的方法。你还可以通过一个const引用来在逻辑上避免无意的写操作。
  实际的“面向对象”的C++代码中,不推荐直接数据成员的访问,取而代之的是使用Get()和Set()方法存取数据,有些人只使用Get,通过返回一个成员的引用来达到读写数据成员的双重目的,这时候,你可以在外部定义一个引用接受函数的返回,从而避免每次都要写(XXX.Get()).Get()这种拖沓的语句来访问一个深层的成员。
  引用的另一个作用,就是“别名”。别名是引用的另一种翻译,很明确的表达了引用的另一个作用。仅仅是为了代码的可读性:

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com)
//下面的代码int i = 0,j = 0;//...for( i = 0; i < 10; i++)for( j = 0; j < 10; j++ )a[i][j] = 0;//你能明白这段代码的含义嘛?有点困难,i和j的含义是不明确的,无法一眼看透。//假如改成这样:const int width = 10;const int height = 10;//...int i = 0,j = 0;//...int &line = i;int &row = j;for(line = 0;line < height;line++)for(row = 0;row < width;row++)a[line][row] = 0;//是不是好了一点?
  这并不是一个典型的例子,因为i和j的定义是任意的,某些情况你必须使用别人给定的名称很郁闷的变量,而他们又必须用来表达截然不同的含义,这时候一个引用往往可以让你清爽很多。

再看下面这个例子:
class CA{int m_i;public:int &i;int const &c_i;CA():i(m_i),c_i(m_i){};};

  这是一个简单的类,与所谓的“面向对象”的方法不同,这里使用引用实现内部数据的公用接口。这个手法用来对应 乾坤一笑 的另一段话:
  这就是偶说的PME模型的问题了,delphi、java、c#之类的语言都提供一种叫做属性的语法,大概是这个样子的:

class A{property int x{get {return x;}set {x = value;}}};A a;
这样, 就可以这么访问了 a.x = 8; int b = a.x;

这比用 a.setx(8); b=a.getx();直观多了。

  你可以用 CA a; a.i访问CA的私有数据成员,达到像属性方法那样的效果。但是这个方法在VC6下的表现却不尽如人意,因为它存储了一个指针用来取代语法上的引用,这导致类体积不必要的扩张,是我们所不希望看到的。也许在实现

来源:http://www.tulaoshi.com/n/20160129/1486142.html

延伸阅读
标签: ASP
  If you store an array in a Session object, you should not attempt to alter the elements of the stored array directly. For example, the following script will not work: <% Session("StoredArray")(3) = "new value" % This is because the Session object is implemented as a collection. The arra...
问题: 如何知道引用的相对应的名称? 我想引用在引用对话框没有的引用,但又不知道它的名称,不知有什么帮助呢? 如:microsoft Office 10.0 Object Library在对话框没有,那要浏览它,请问它相对应的名称是什么呢? 还有如果看到别的人数据库有些引用,而在我的数据库的引用对话框上找不到的呢?  回答: 用以下代码显示出现在已经引用的所有...
标签: excel
Excel公式引用方式转换   Excel 2003如何使用条件格式设置自动提醒?   如图: 以提前3天红底色提醒为例: 选中区域--点"格式"--"条件格式"--"公式"--"=$B2-3=TODAY()"--"格式"--'图案"--选红色--"确定',如图: --"确定",效果如图:...
标签: 电脑入门
相信在学习Excel的朋友都知道Excel的功能强大吧,那么Excel单元格引用是怎么回事呢?今天图老师小编就给大家详细讲讲Excel单元格引用的相关内容,相信大家在看了图老师小编写的内容之后肯定会有帮助的,好了,下面图老师小编就给大家具体说说: Excel单元格引用包括相对引用、绝对引用和混合引用三种。 一、绝对引用 单元格中的绝对单元格引...
标签: Web开发
作为一种标记语言,HTML 在互联网中的广泛采用佐证了它在发布内容方面的实用性是无与伦比的。HTML 向结构内容提供各种标记,其中包括处于不同级的标题标记,例如从 h1 到 h6,或定义列表的标记,例如 ul 或 ol。HTML 文档是简单的文本文档,可以使用任何编辑器加以创建或从当前办公产品套件中导出的文档进行创建。HTML 缺乏对一些项目(例...

经验教程

817

收藏

98
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部