设为首页 加入收藏

TOP

条款1:仔细区别pointers和references
2013-10-07 14:02:17 来源: 作者: 【 】 浏览:108
Tags:条款 仔细 区别 pointers references

基础议题

Basics

基础议题。是的,pointers(指针)、references(引用)、casts(类型转换)、arrays(数组)、constructors(构造函数)--再没有比这些更基础的议题了。几乎最简单的C++(www.cppentry.com) 程序也会用到其中大部分特性,而许多程序会用到上述所有特性。

尽管你可能已经十分熟悉语言的这一部分,但有时候它们还是会令你吃惊。特别是对那些从C 转战到C++(www.cppentry.com) 的程序员,因为references,dynamic casts,default constructors 及其他non-C性质背后的观念,往往带有一股黝黯阴郁的色彩。

这一章描述 pointers 和 references 的差异,并告诉你它们的适当使用时机。本章介绍新的C++(www.cppentry.com) 转型(casts)语法,并解释为什么新式转型法比旧式的C 转型法优越。本章也检验了C的数组概念及 C++(www.cppentry.com) 的多态(polymorphism)概念,并说明为什么将这两者混用是不智之举。最后,本章讨论 default constructors(默认构造函数)的正方和反方意见,并提出一些建议做法,让你回避语言的束缚(因为在你不需要default constructors 的情况下,C++(www.cppentry.com) 也会给你一个)。

只要留心下面各条款的各项忠告,你将向着一个很好的目标迈进:你所编写的软件可以清楚而正确地表现出你的设计意图。

条款1:仔细区别pointers和references

Pointers 和 references 看起来很不一样(pointers 使用"*"和"->"操作符,references则使用"."),但它们似乎做类似的事情。不论 pointers 或是 references 都使你得间接参考其他对象。那么,何时使用哪一个?你心中可有一把尺?

首先你必须认知一点,没有所谓的 null reference。一个 reference 必须总代表某个对象。所以如果你有一个变量,其目的是用来指向(代表)另一个对象,但是也有可能它不指向(代表)任何对象,那么你应该使用pointer,因为你可以将pointer 设为 null。换个角度看,如果这个变量总是必须代表一个对象,也就是说如果你的设计并不允许这个变量为 null,那么你应该使用 reference。

"但是等等"你说,"下面这样的东西,底层意义是什么呢?"

  1. char *pc = 0;       // 将 pointer 设定为 null。  
  2. char& rc = *pc;     // 让 reference 代表 null pointer 的解引值。 

哦,这是有害的行为,其结果不可预期(C++(www.cppentry.com) 对此没有定义),编译器可以产生任何可能的输出,而写出这种代码的人,应该与大众隔离,直到他们允诺不再有类似行为。如果你在你的软件中还需担心这类事情,我建议你还是完全不要使用 references 的好,要不就是另请一个比较高明的程序员来负责这类事情。从现在起,我们将永远不再考虑"reference 成为 null"的可能性。

由于 reference 一定得代表某个对象,C++(www.cppentry.com) 因此要求 references 必须有初值:

  1. string& rs;                 // 错误!references 必须被初始化。  
  2. string s("xyzzy");  
  3. string& rs = s;             // 没问题,rs 指向 s。 

但是 pointers 就没有这样的限制:

  1. string *ps;             // 未初始化的指针,有效,但风险高。 

"没有所谓的 null reference"这个事实意味使用 references 可能会比使用 pointers 更富效率。这是因为使用 reference 之前不需要测试其有效性:

  1. void printDouble(const double& rd)  
  2. {  
  3.     cout << rd;     // 不需要测试 rd,它一定代表某个 double。  

如果使用 pointers,通常就得测试它是否为 null:

  1. void printDouble(const double *pd)  
  2. {  
  3.   if (pd) {       // 检查是否为 null pointer。  
  4.     cout << *pd;  
  5.   }  

Pointers 和 references 之间的另一个重要差异就是,pointers 可以被重新赋值,指向另一个对象,reference 却总是指向(代表)它最初获得的那个对象:

  1. string s1("Nancy");  
  2. string s2("Clancy");  
  3.  
  4. string& rs = s1;            // rs 代表 s1。  
  5. string *ps = &s1;           // ps 指向 s1。  
  6. rs = s2;                    // rs 仍然代表 s1,  
  7.                             // 但是 s1 的值现在变成了"Clancy"。  
  8. ps = &s2;                   // ps 现在指向 s2,  
  9.                             // s1 没有变化。 

一般而言,当你需要考虑"不指向任何对象"的可能性时,或是考虑"在不同时间指向不同对象"的能力时,你就应该采用 pointer。前一种情况你可以将 pointer 设为 null,后一种情况你可以改变 pointer 所指对象。而当你确定"总是会代表某个对象",而且"一旦代表了该对象就不能够再改变",那么你应该选用 reference。

还有其他情况也需要使用 reference,例如当你实现某些操作符的时候。最常见的例子就是 operator[]。这个操作符很特别地必须返回某种"能够被当做 assignment 赋值对象"的东西:

  1. vector<int> v(10);   // 产生一个 int vector,大小为 10。  
  2.                         // vector 是 C++(www.cppentry.com) 标准程序库(见条款 35)  
  3.                         // 提供的一个 template。  
  4. v[5] = 10;              // assignment 的赋
    值对象是 operator[] 的返回值。 

如果 operator[] 返回 pointer,上述最后一个语句就必须写成这样子:

  1. *v[5] = 10; 

但这使v 看起来好像是个以指针形成的 vector,事实上它不是。为了这个因素,你应该总是令 operator[] 返回一个 reference。条款30 有一个例外,十分有趣。

因此,让我做下结论:当你知道你需要指向某个东西,而且绝不会改变指向其他东西,或是当你实现一个操作符而其语法需求无法由 pointers 达成,你就应该选择 references。任何其他时候,请采用 pointers。

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇条款20:协助完成"返回值优.. 下一篇条款16:谨记 80-20 法则

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: