在所有情况下,使用C++引用而不是指针真的是最佳实践吗

Is it really the best practice to prefer C++ references to pointers in all situations?

本文关键字:真的 指针 最佳 情况下 使用 引用 C++      更新时间:2023-10-16

C++常见问题解答说:

"尽可能使用引用,必要时使用指针。"

我觉得没有上面说的那么容易。引用通常更好地指向指针的原因已经得到了很好的讨论。因此,我更愿意讨论引用有意义但极不寻常且感觉不对劲的特殊情况:

对我来说,最明显的情况是它们在通用数据结构中的使用,如树或链表。他们的接口当然可以使用引用来实现,而且感觉更安全,但我还没有看到任何一个实现会利用引用,例如:

Node *parent = n.parent(); // parent might be unset -> pointer
Node &child = n.child(5); // child is always valid -> reference

尽管它看起来很有吸引力,但它导致了这样的代码:

if(parent == &child) ... //  weird, unusual at least?

我想知道,这就是纯C++的含义吗?

每次我试图尽可能盲目地使用引用时,我都会遇到各种类似的不一致,并以各种丑陋的方式混合指针和引用

总之,为什么运算符new一开始就不返回对新实例的引用而不是指针?(并在出现错误时抛出):

Node &n = new Node;
delete &n;

这是一个荒谬的例子,但这不就是"纯C++"吗?

一旦初始化,就不能将引用修改为引用不同的对象。但是指针可以修改为在运行时引用不同的对象。

一般经验

如果希望变量在其生命周期内指向不同的对象,请使用指针。

如果您只想使用一个变量作为另一个变量的别名,请使用引用。

As参数

我们有时会将参数作为引用(const/non-const)传递。这将有助于避免每次调用函数时复制整个对象。因此,当经过大尺寸的物体时,这将是非常有意义的。

如果函数需要接收一些参数(可选为null),则可以使用指针。但是,同样,您可以为任何类定义一个静态null对象,并且可以使用它。

As返回值

每当我们重载运算符时,例如[]或<lt;,我们会返回参考资料。这是因为,如果我说vec[0]=10,它实际上应该将值10分配给vec中的位置0。这里我不能不使用指针,原因很明显*vec[0]=10不仅看起来好看。此外,您应该保证,当您返回引用时,它总是引用一个对象(它永远不应该为null)。

同样,当函数可以返回NULL值时,请使用指针,否则可能需要为该类声明一个静态NULL对象。

作为数据成员

引用应该在构造函数中初始化。因此,一旦构建了对象,就不能更改它们。

因此,如果您需要一个在类的生存期内需要指向不同对象的变量,那么指针将是一个不错的选择。

我认为通用数据结构属于"必要时使用指针"子句。也就是说,由于引用是恒定的(即它们总是引用同一个对象),在链表或树节点结构中使用引用意味着你不能插入新节点或从数据结构中删除旧节点,这通常会违背目的。

正如有人在评论中所说,我认为这个建议真的适用于函数论点。传递引用而不是指针可以避免为每个函数添加空指针处理逻辑,这在代码大小和清晰度方面带来了很多好处。

如果您熟悉关系数据库中的NULL和NOT NULL列,或者熟悉XSD中强制元素和可选元素之间的区别,那么您可能能够从这样的域中绘制一个有用的平行图来指导您。

引用将代表固定的、独立的、不可为null的变量。对于那些真正需要传递"无值"的指针,或者在明确需要执行指针运算的地方(例如使用数组)。这些并不是唯一的区别,但大多数不同的语法都是从那里开始的。

概括一下:reference=NOT NULL和只读。指针=灵活且有点危险。

"new"运算符分配内存(就像C中的malloc一样)。因为C++没有实现垃圾收集器(如Java或C#),所以内存可能会耗尽。因此,当new无法分配内存时,会返回一个NULL值。通过这种方式,您可以测试分配是否成功。

不能将引用与新运算符一起使用,因为内存不足可能会导致赋值为NULL值。