【发布时间】:2011-06-10 15:03:00
【问题描述】:
从我最近的问题 (Why is a c++ reference considered safer than a pointer?) 中发生的讨论中,我想到了另一个问题:在 c++ 中引入引用的原因究竟是什么?
【问题讨论】:
从我最近的问题 (Why is a c++ reference considered safer than a pointer?) 中发生的讨论中,我想到了另一个问题:在 c++ 中引入引用的原因究竟是什么?
【问题讨论】:
Stroustrup 的Design and Evolution of C++ 第 3.7 节描述了在语言中引入引用。如果您对 C++ 任何特性背后的原理感兴趣,我强烈推荐这本书。
引入引用主要是为了支持运算符重载。 Doug McIlroy 回忆说,有一次我向他解释了当前运营商重载计划的前身存在的一些问题。他使用了reference这个词,效果令人吃惊,我低声说“谢谢”,然后离开他的办公室,第二天再次出现,目前的计划基本完成。 Doug 让我想起了 Algol68。
C 按值传递每个函数参数,如果按值传递对象效率低下或不合适,用户可以传递指针。此策略在使用运算符重载的情况下不起作用。在这种情况下,符号方便是必不可少的,因为如果对象很大,则不能期望用户插入地址运算符。例如:
a = b - c;是可接受的(即传统的)表示法,但是
a = &b - &c;不是。无论如何,
&b - &c在 C 中已经有了意义,我不想改变它。初始化后无法更改引用所指的内容。也就是说,一旦 C++ 引用被初始化,就不能重新绑定。我过去曾被 Algol68 引用所困扰,其中
r1 = r2可以通过r1分配给所引用的对象,或者根据 @ 的类型为r1分配一个新的引用值(重新绑定r1) 987654329@。我想避免在 C++ 中出现此类问题。
【讨论】:
您需要它们来进行运算符重载(当然,我们现在可以深入研究“引入运算符重载的基本原理是什么?”)
如果没有引用,您将如何键入std::auto_ptr::operator*()?还是std::vector::operator[]?
【讨论】:
引用隐式绑定到对象。当您考虑绑定到临时对象或运算符重载之类的事情时,这具有很大的优势 - C++ 程序将充满 & 和 *。当您考虑它时,指针的基本用例实际上是引用的行为。此外,搞砸引用要困难得多——你自己不执行任何指针运算,不能自动从数组转换(一件可怕的事情)等等。
引用比指针更简洁、更简单、更安全。
这很有趣,因为大多数其他语言没有像 C++ 那样的引用(别名),它们只有指针样式的引用。
【讨论】:
如果代码获取变量的地址并将其传递给例程,则编译器无法知道该地址是否会在被调用例程退出很长时间后存储在某个地方并使用,并且可能在变量停止运行之后存在。相比之下,如果代码传递为例程提供了对变量的引用,则它更能确保该引用仅在该例程运行时使用。一旦该例程返回,该引用将不再被使用。
由于 C++ 允许代码获取引用地址这一事实,事情最终变得有点“崩溃”。提供此功能是为了允许与期望指针而不是引用的旧例程兼容。如果一个引用被传递给一个例程,该例程获取它的地址并将其存储在某个地方,那么所有的赌注都会被取消。另一方面,如果政策禁止以任何可能持久的方式使用引用的地址,则可以很好地获得引用提供的保证。
【讨论】:
允许运算符重载。他们希望操作符对对象和指针都是可重载的,因此他们需要一种通过指针以外的方式引用对象的方法。因此引入了参考。在《C++的设计与演进》中。
【讨论】: