![More Effective C++:35个改善编程与设计的有效方法(中文版)](https://wfqqreader-1252317822.image.myqcloud.com/cover/11/33381011/b_33381011.jpg)
条款 1:仔细区别 pointers和 references
Pointers 和 references 看起来很不一样(pointers 使用“*”和“->”操作符,references则使用“.”),但它们似乎做类似的事情。不论 pointers 或是 references都使你得间接参考其他对象。那么,何时使用哪一个?你心中可有一把尺?
首先你必须认知一点,没有所谓的 null reference。一个 reference 必须总代表某个对象。所以如果你有一个变量,其目的是用来指向(代表)另一个对象,但是也有可能它不指向(代表)任何对象,那么你应该使用 pointer,因为你可以将 pointer设为 null。换个角度看,如果这个变量总是必须代表一个对象,也就是说如果你的设计并不允许这个变量为 null,那么你应该使用 reference。
“但是等等”你说,“下面这样的东西,底层意义是什么呢?”
![](https://epubservercos.yuewen.com/B16285/17829663508311206/epubprivate/OEBPS/Images/12570_27_1.jpg?sign=1739282338-9YzSI7iEJqwsRykZwCfrOeuR23LryYk4-0-0a05f1aa81c323335ee996158fbf4181)
哦,这是有害的行为,其结果不可预期(C++对此没有定义),编译器可以产生任何可能的输出,而写出这种代码的人,应该与大众隔离,直到他们允诺不再有类似行为。如果你在你的软件中还需担心这类事情,我建议你还是完全不要使用references 的好,要不就是另请一个比较高明的程序员来负责这类事情。从现在起,我们将永远不再考虑“reference 成为 null”的可能性。
由于 reference 一定得代表某个对象,C++因此要求 references 必须有初值:
![](https://epubservercos.yuewen.com/B16285/17829663508311206/epubprivate/OEBPS/Images/12570_27_2.jpg?sign=1739282338-lo8UGGKMyP4B1d3Hpdj4lkt3oDC4C9Hd-0-00d87d1b35fb85004f71396caf0d4602)
但是 pointers 就没有这样的限制:
![](https://epubservercos.yuewen.com/B16285/17829663508311206/epubprivate/OEBPS/Images/12570_27_3.jpg?sign=1739282338-702pWaFxBPuYO34L6U5HrekZpMJY00E9-0-72d8d1d994bf81c90b72feab9e978c36)
“没有所谓的 null reference”这个事实意味使用 references 可能会比使用
pointers 更富效率。这是因为使用 reference 之前不需要测试其有效性:
![](https://epubservercos.yuewen.com/B16285/17829663508311206/epubprivate/OEBPS/Images/12570_27_4.jpg?sign=1739282338-ykeBFkKrRgEpdV7mi17yNFqpUPbBotJH-0-1b42192d7f25f99d42abd192beae572d)
如果使用 pointers,通常就得测试它是否为 null:
![](https://epubservercos.yuewen.com/B16285/17829663508311206/epubprivate/OEBPS/Images/12570_27_5.jpg?sign=1739282338-Wy1JxUFiCvhowwxgDDFyDUiDfx4YUgQa-0-072340d7a548ce9c4ee2bdeffb3f9979)
Pointers 和 references 之间的另一个重要差异就是,pointers 可以被重新赋值,
指向另一个对象,reference 却总是指向(代表)它最初获得的那个对象:
![](https://epubservercos.yuewen.com/B16285/17829663508311206/epubprivate/OEBPS/Images/12570_28_1.jpg?sign=1739282338-us9VXHMQfHBvVwAAWUom67NzcJDGPEJL-0-1282f371edba3263fb6b1eff1876c039)
一般而言,当你需要考虑“不指向任何对象”的可能性时,或是考虑“在不同时间指向不同对象”的能力时,你就应该采用 pointer。前一种情况你可以将 pointer设为 null,后一种情况你可以改变 pointer 所指对象。而当你确定“总是会代表某个对象”,而且“一旦代表了该对象就不能够再改变”,那么你应该选用 reference。
还有其他情况也需要使用 reference,例如当你实现某些操作符的时候。最常见的例子就是 operator[]。这个操作符很特别地必须返回某种“能够被当做
assignment 赋值对象”的东西:
![](https://epubservercos.yuewen.com/B16285/17829663508311206/epubprivate/OEBPS/Images/12570_28_2.jpg?sign=1739282338-kcregVeQeHaxZM1wREZp3HQ4Jp04nYde-0-97c63ab73d56d88c7145c9a4909c1483)
如果 operator[] 返回 pointer,上述最后一个语句就必须写成这样子:
![](https://epubservercos.yuewen.com/B16285/17829663508311206/epubprivate/OEBPS/Images/12570_28_3.jpg?sign=1739282338-KOVhJZZx4kgPrt8aAQiXEL3rmyBAwAdS-0-2bea377404916a033e42112c2a099623)
但这使 v 看起来好像是个以指针形成的 vector,事实上它不是。为了这个因素,你应该总是令 operator[] 返回一个 reference。条款 30 有一个例外,十分有趣。
因此,让我做下结论:当你知道你需要指向某个东西,而且绝不会改变指向其他东西,或是当你实现一个操作符而其语法需求无法由 pointers 达成,你就应该选择 references。任何其他时候,请采用 pointers。