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